How to know when a property has been updated from it's connected attribute? - lit-element

Given:
#property({type: Boolean, attribute: 'some-attr'}) someAttr = false;
I was expecting to see updated being fired once 'some-attr' value gets updated in the DOM.
However, updated doesn't get fired at all.
Is my expectation wrong, or should I set things up differently?

Looking at Elm's discussion of properties vs attributes, the documentation of the Html.Attributes module's attribute function, and the Elm documentation on custom elements, I am pretty sure, that this is caused by simply binding an elm expression to attribute some-attr of the LitElement based custom element. I.e. the DOM attribute will always be present and hence the corresponding property always be true.
The default converter for Boolean (activated by providing type:Boolean to the decorator) mimicks the behaviour of HTML attributes used as flags (e.g. disabled on an <input> element): If the attribute is present (no matter the value), the flag is set (true). The implementation is really straight forward, if you want to look at it in the sources: https://github.com/Polymer/lit-element/blob/master/src/lib/updating-element.ts#L163
I see these options for your problem:
Implement some extra logic in Elm to add / remove the presence of the attribute.
Create your own attribute converter for the LitElement based custom element.
Use another default converter (e.g. for String, the "default" default converter) and implement the custom logic inside the LitElement (e.g. using a derived value).
Of these 3 options, I would generally recommend the first one, as your custom element then still behaves naturally, i.e. if some-attr should be a flag (boolean attribute), then following which HTML semantics, it should be defined by its presence, not its value. This allows you to re-use it in other projects without surprising other developers.
That being said, there may of course be project-specific requirements, that are more important. E.g. if you only use this custom element in this one project with Elm, your road to success may be faster going for options 2 or 3.

Related

Cannot get itemDescription on f:selectItems to have an effect

The doc says:
"itemDescription: evaluates to a String that will serve as the description to be shown for the item."
http://docs.oracle.com/javaee/6/javaserverfaces/2.1/docs/vdldocs/facelets/f/selectItems.html
http://docs.oracle.com/javaee/6/javaserverfaces/2.1/docs/vdldocs/facelets/f/selectItem.html
I'm not getting any title attribute added to the resulting option element in the DOM or anything, not even when setting a literal String as its value (neither on f:selectItem nor f:selectItems, each tried seperately, the latter with a c:forEach over the list items which showed up correctly with their labels).
Some forum posts seemed to suggest people use it for tooltips.
The doc isn't being entirely clear, is the itemDescription attribute on the component even meant to be rendered as a tooltip/title? And if not, what's it good for?
I think BalusC already answered it in https://stackoverflow.com/a/25512124/3280015, which I initially overlooked.
"While creating the custom renderer, you could make use of the unused(!) description property of the UISelectItem class."
So it is currently simply unused and left for potential use by developers. Maybe that's what the Doc means by:
"for use in development tools."

When to use parameterized method invocations introduced with EL 2.2 (especially in JSF 2.x )?

In the past I used a lot of getter and setter methods to move as much boolean logic as possible from facelet files to JSF backing beans.
This way, the interface of a view was given by the getter and setter methods of its backing bean as well as by the action methods of the backing bean.
An advantage of this approach is that the facelet files are rather logic-free and ,therefore, all logic is within the backing beans and can be unit tested.
But with EL 2.2 another programming style became possible. In EL 2.2 you can invoke methods with expressions like
#{bean.collection.size()},
#{bean.collection.add(elem)},
#{bean.property.substring(0, bean.property.indexOf(something))}.
Is the usage of rather complex expressions like parameterized method invocations good style now or do you rather advise against using such expressions?
Is there a rule of thumb when to use the new method invocation expressions and when not?
The major guideline is the following: reduce as much 'model' logic from the view as possible and leave only the 'view' logic. EL 2.2 made possible some model simplification and reduced the need for creation of artificial properies of JSF beans. Invocation of methods with parameters also enables to pass the necessary information from the view to the controller which would be tedious without that opportunity.
You can call arbitrary methods to access the model from the view that the view part relies on, but you should never call methods that modifies the model from the view.
Let me elaborate on that.
Some legal examples:
evaluate non-accessor methods when building view:
render UI components based on some conditions like rendered="#{request.isUserInRole('administrator')}";
make collection modifications where necessary like <ui:repeat value="#{bean.set.toArray()}" ... >
conditionally evaluate UI component / HTML element attributes like class="#{bean.name.contains('special') ? 'special' : ''}";
output non-accessor data like there are #{bean.list.size()} elements.
pass information to the controller in action methods or listeners:
execute action methods with currently iterated variables like var="data" and action="#{bean.action(data)}" with public String action(Data data);
pass additional data, like current iteration index, in listeners like varStatus="status" and actionListener="#{bean.action(status.index)}" with public String action(int index).
Some to-be-avoided examples:
use EL operators when possible:
use #{not empty bean.list} instead of #{bean.list.size() gt 0}.
use method call with parameters instead of extending the model:
use #{bean.name.contains('special')} instead of #{bean.special} with public boolean isSpecial() {return name.contains("special");}.
prefer leaving view logic in view for plain rendering of the right things and create model logic in case it applies purely to the model:
in case you need to perform some calculations to change the appearance of an object, do that in view directly without changing the model, in case some property is inherent to the model itself, introduce it directly in the model and refer to it from the view.
Some illegal examples:
modify the model from the view:
do not use EL 2.2 possibility of calling methods with parameters to break the MVC paradigm, i.e. do not call #{bean.list.add(element)} from the view side.
Of course, all things said apply to the cases that your goals don't contain targeting at the older servers without EL 2.2 support.
As a bigger picture, I'd recommend to also see BalusC's explanation of what MVC architecture represents within the context of JSF.
Personally, i prefer using "complex" EL expressions when really needed, and take any bit logic/traitement to the correspondant managed-beans.
For example: the first example you put is the only one that i may sometimes use directly, the two others however should be for me put in action methods with void/String returning type according to the need.
Use El 2.2 to reduce our JSF code, e.g. setPropertyActionListener is made redundant, see
JSF Core Tag :setPropertyActionListener vs attribute vs param

How to access a composite component's sibling via clientId

I have a composite component that bundles some input fields. The component will be used multiple times on a page and contains a button to copy the values of another of these components. For this I would need to access one of those siblings via its clientId as a target for an
<f:ajax execute=":XXX:siblingId" render="...">
My problem lies in constructing this ID. I have the name of the sibling and I can make sure that it is located in the same naming container as the component that contains the copy button, but I can't control the complete nesting hierarchy, so it might be :form:foo:bar:parent:child or just form:parent:child. So essentially I would want to get the prefix of the current composite component, but without the component's own ID and then attach the ID of the component from which to copy.
This is similar to these questions:
How to address the surrounding naming container in jsf
How to access the parent naming container of composite
However, both answers make use of PrimeFaces-sepcific features like #parent and widgetVar, which does not apply to my project.
When experimenting with EL's implicit objects I basically tried the same things as the poster of the second question - with the same results: cc.parent.clientId is always empty. I also tried cc.namingContainer.clientId and some combinations of the two, alas - no success. Especially the fact that parent does not work as expected confuses me...
So: Is there a component-library-agnostic way to access the "path" of containing naming containers for a composite component? How is the parent object supposed to work, especially: when can we use it and when not?
PS: I was thinking about using the composite's full clientId and then trimming its actual ID with fn:split, however, if there was a more direct way I'd be happy to use it.
The #{cc.parent} resolves to UIComponent#getCompositeComponentParent() which returns the closest parent composite component. In other words, it returns only non-null when the composite component is by itself nested in another composite component.
The #{cc.namingContainer} simply refers to #{cc} itself, fully conform as specified in UIComponent#getNamingContainer():
Starting with "this", return the closest component in the ancestry that is a NamingContainer or null if none can be found.
Composite components namely implicitly implement NamingContainer themselves.
So your attempts unfortunately won't work. I also do not see any "standard API" ways to achieve the concrete functional requirement. The CompositeComponentAttributesELResolver causes that the #{cc.parent} doesn't resolve to UIComponent#getParent() which is what you ultimately want.
You can however provide a custom UIComponent implementation for the composite which adds an extra getter with an unique name which in turn properly delegates to UIComponent#getParent().
Here's a kickoff example:
#FacesComponent("myComposite")
public class MyComposite extends UINamingContainer {
public UIComponent getParentComponent() {
return super.getParent();
}
}
If you register it as follows in the composite interface:
<cc:interface componentType="myComposite">
then you'll be able to use
#{cc.parentComponent.clientId}
to get the client ID of the real parent UIComponent.
Ultimately you should be able to use the following construct to refer the sibling:
process=":#{cc.parentComponent.clientId}:siblingId"

Assigning individual View Models to Nested Views?

I have a MainView which has an associated MainViewModel in my WPF application, assigned via its contructor.
App > start up uri > MainWindow.xaml
public MainWindow()
{
InitializeComponent();
var viewModel = new MainViewModel();
DataContext = viewModel;
}
My MainView holds as many as four nested views or child views who are hidden and displayed based upon the button that has been clicked on the MainView. So we toggling the visibility property vi a binding which gets updated via command bindings assigned to each button on the MainView.
Each nested View does not have an associated ViewModel, all bindings found on child views find their information in the MainViewModel. So binding system ends waling up the UI tree of the app to find out that the parent 'MainView' has an associated ViewModel.
So overall there is 'ONE' -> ViewModel. This seems to work fine and but as expected this VM has gotten to big and needs re-factoring. It holds information that contextually it should not. But this is a proof concept application. So i decided to keep it simple and make sure it was do-able.
PROBLEM:
When i tried assigning a empty view with an empty view model I noticed binding errors in the output window and as expected weird and broken behaviour. Which makes no sense ... Is there a more clear and concise way of letting WPF know how to handle any bindings it finds in a nested view control? I thought if each view's constructor assigned itself a corresponding VM as shown above, then it should work as this logically makes sense. Unfortunately all buttons on the MainView stop working when the corresponding view it is designated to switch on and hide the others has an associated ViewModel. On some buttons it works and the others it does not? This is really weird?
As mentioned in my answer above, the problem was that WPF binding system was struggling to to resolve bindings at run time. The main view has its associated view model instantiated and assigned via the Main View contructor and this pattern is repeated for all nested views that the MainView also houses.
By default, I tend to use the implied binding syntax which means that without explicitly specifiying a source the binding system will try to resolve the name you supply in the binding. So it's all implied and nothing is explicitly set!
Upgrading each nested view to have its own view model makes this auto discovery/resolution of bindings go a little crazy and I have not explicitly told the binding system where to find the property I am looking for hence the output window binding errors.
This leads to unexpected behaviour as the output window was telling that it was trying to resolve binding expressions in nested views --> viewmodels. When in actual fact that VM it is looking in, IS EMPTY!
So clearly the binding system is good when you do not explicitly set a source property inside the binding syntax. It is clever enough to find things on its own. In my case it needed some extra help, as it was unsure as to where to find things.
SOLUTION:
Remove the constructor declaration for the MainViewModel in the MainView constructor.
Scope in an xmlns for ViewModels namesapce into your MainView.xaml
Create a window resource inside the MainView .xaml
Give the resource a key.
Upgrade all your bindings in the MainView xaml file to include source property.
Give the source property a static resource binding that points to your ViewModel key value set up in step 4.
Only do step 6 for bindings who refer to the ViewModel that is associate with the MainView.
All nested views are to be left alone, they should handle their own bindingds in their own xaml files. The MainView simply instantiates them and places them onto the UI. For me this was the case, I did not have any more bindings concerning my nested views. All Bindings that lived on the MainView.xaml file referred to data in the MainViewModel.cs. This makes alot easier when viewing your problem.
For some reason the editor was being awkward so I chose to omit any sample code but the steps above are descriptive enough to follow the steps that I took. Above is what worked for me.
ANOTHER WAY OF SUMMING UP THIS PROBLEM
Most books teach the shorter binding syntax
What happens when more than one data context is available?
How is the binding system supposed to know how to resolve your short hand binding expressions.

Replacing Views2 base field handler

I want to add some rendering options to Views2 field handler (similar to 'Output this field as link' or 'Rewrite the output of this field') for a greater control over rendering of HTML markup (I need to add some extra attributes to tags). I want this additional options to be available for all (or at least most of the fields). Is it possible to replace default Views2 field handler (i.e. views_handler_field class) with my own field handler? There is a hook for submitting own handlers (hook_views_handlers) and there is a hook to tell other modules what handler should be used for given field (hook_views_data_alter). I also don't see a way to override default inheritance pattern for view_handler_field and its descendants. And extending every single field handler provided by other modules with my own classes seems to be pointless. Am I right saying that this cannot be the right way to solve this problem?
If I am right, what is another way to (1) extend field options form with some inputs and (2) alter rendering of this field based on inputs. I guess (1) could be achieved by altering form by default Drupal hook, but render method belongs to given field handler and I don't see a way to intercept its call and output altered markup.
In theory you could use a non-existant hook_views_handlers_alter to change the path of a class which is somewhere

Resources