What is the difference between one-time and one-way binding in UI5?
Are there any user specific use-cases where I would use each of them?
I could not get much info from the documentation.
One-way
What it does: unidirectional data flow. Changes in the model data (e.g. via setProperty) are steadily propagated to the interested elements in the UI.
Use-case: one prominent example is the device model (a one-way JSONModel). It shouldn't accept any user inputs that might update the device information accidentally.
We have to set the binding mode to OneWay as the device model is read-only and we want to avoid changing the model accidentally when we bind properties of a control to it. By default, models in OpenUI5 are bidirectional (TwoWay). When the property changes, the bound model value is updated as well.
One-time
What it does: one-time data flow. When the binding object is evaluated, its corresponding model data are read and written to the element properties once, and never again.
Why it exists: it all comes down to the number of change listeners. Fewer listeners means less memory allocation and less stuff to maintain during the runtime. The binding mode OneTime has thus the potential, compared to other binding modes, to optimize performance and memory consumption.
When to use: for static, non-mutating data.
Note: for property bindings, oBindingInfo.value (since 1.61) can be also defined for static values instead of relying on a model in property binding.
Use-case: the prominent example here is the ODataMetaModel. From its API reference:
This model is read-only and thus only supports OneTime binding mode. No events are fired!
For more information, see the documentation topic "Data Binding".
Assigning binding modes in UI5
Specific to a binding:
<Text text="{ path: '...', mode: 'OneTime' }"/>
For all bindings of the model:
myModel.setDefaultBindingMode("OneTime");
Or in the app descriptor in case of an ODataModel:
{
"sap.ui5": {
"models": {
"myODataModel": {
"dataSource": "...",
"settings": {
"defaultBindingMode": "TwoWay"
},
"preload": true
}
}
}
}
In Expression Binding, binding modes can be defined with the following syntax:
myProperty="{:= ...}" ⇒ OneTime
myProperty="{= ...}" ⇒ OneWay
Custom formatter in binding infos (e.g. <Text text="{ ..., formatter: '.createText' }">) as well as composition with string-literals (e.g. "My Name is {/name}") forces the binding to become one-way. Use type in order to keep the binding two-way.
Related
TL;DR: In case of a reusable component which has some complicated logic for managing its own state (think: a facebook comment textarea with autocompleter, emoji etc) how does one use store, actions and reducers to manage the state of multiple instances of this component spread across whole website?
Consider the real-world example from the official redux repo.
In it we have:
a RepoPage, which displays list of users who have starred a particular repo,
a UserPage, which displays a list of repos which are starred by particular user
a List, which is generic enough that it can display list of users or repos, provided the items and way to renderItem. In particular RepoPage uses User component to display each of users who starred the repo, and UserPage uses a Repo component to display each of starred repos.
Assume that I really want all of the state to be in Redux.
In particular, I want the state of every List on every RepoPage and UserPage to be managed by Redux. This is already taken care of in the example, by a clever three-level deep tree:
at the top level the key says what kind of component data is it (in the example it is called store.pagination)
then there is a branch for each particular type of context in which the component can be (store.pagination.starredByUser, store.pagination. stargazersByRepo)
then there are as many keys as there are unique contexts (store.pagination.starredByUser[login], store.pagination. stargazersByRepo[repo])
I feel that these three levels correspond also to: component type, parent type, parent id.
But, I don't know how to extend this idea, to handle the case in which the List component itself had many children, with a state worth tracking in Redux.
In particular, I want to know how to implement a solution in which:
User component remains intact
Repo component has a button which toggles its background color
the state of each Repo component is managed by Redux
(I'm happy to use some extensions to Redux, which still use reducers, but don't want to go with "just keep it in React local state", for the purpose of this question)
My research so far:
it looks like in Elm the Actions (messages) are algebraic data types which can be nested in such a way, that a parent component can unpack an "outer envelope" of the message and deliver a inner action intended for child to the child reducer (updater).
since it is a convention in Redux to use a string as the type of action, a natural translation of the above idea is to use prefixing, and this seems to be what prism (foremly known as redux-elm) does: the action.type is comprised of substrings which tell the path through components' tree. OTOH in this comment the prism author tomkis explains that the most important part of Elm Architecture that Redux is missing is composition of actions
the two above approaches seem to be expanded versions of approaches described in Reusing Reducer Logic
I haven't fully grasped how redux-fly works internally, but it seems to use the payload, not the action.type to identify a component instance by its mounting path in the store which also corresponds to a path in the components tree because of the way it is constructed manually by components
WinAPI, which to me seems quite similar to Redux if you squint, uses unique hWnd identifier for each control, which makes it super easy to check if action was intended for you, and decide where should be your state in the store.
The above idea could probably lead to something described in Documentation suggestion/discussion: Reusing Reducer Logic where each type of component has its own flat subtree indexed by unique id.
Another idea descibed in the linked thread linked above is to write a reducer for a particular type of component once, and then let the reducer for the parent component call it (which also means, that the parent is reponsible to decide where in the store the state of the child is located - again, that seems similar to Elm Architecture to me)
A very interesting discussion More on reusability for custom components in which details of a proposal vary similar to the one above is presented
in particular above discussion contains a proposition by user nav, to organize the store tree recursively in such a way, that a state of a component is subtree in two kinds of branches: one for private stuff, and the other for "tables" of child components, where each class of child component has its own "table", and each instance of child has a unique key in that table, where its state is recursively stored. The unique keys which give access to these children are stored in the "private" section. This is really similar to how I imagine WinAPI :)
another elm-inspired proposition by user sompylasar from the same thread is to use actions which contain actions for children as a payload in a "matrioshka" style, which in my opinion mimick how algebraic types constructors are nested in Elm
redux-subspace was recommended in discussion about Global Actions for prism, as a library which is both Elm-inspired and lets you have global actions.
I will try to explain one of idea which is inspired by Elm lang and has been ported to Typescript:
Let's say we have very simple component with the following state
interface ComponentState {
text: string
}
Component can be reduced with the following 2 actions.
interface SetAction {
type: 'SET_VALUE', payload: string
}
interface ResetAction {
type: 'RESET_VALUE'
}
Type union for those 2 actions (Please look at Discriminated Unions of Typescript):
type ComponentAction = SetAction | ResetAction;
Reducer for this should have thw following signature:
function componentReducer(state: ComponentState, action: ComponentAction): ComponentState {
// code
}
Now to "embed" this simple component in a larger component we need to encapsulate data model in parent component:
interface ParentComponentState {
instance1: ComponentState,
instance2: ComponentState,
}
Because action types in redux need to be globally unique we cannot dispatch single actions for Component instances, because it will be handled by both instances. One of the ideas is to wrap actions of single components into parent action with the following technique:
interface Instance1ParentAction {
type: 'INSTNACE_1_PARENT',
payload: ComponentAction,
}
interface Instance2ParentAction {
type: 'INSTNACE_2_PARENT',
payload: ComponentAction,
}
Parent action union will have the following signature:
type ParentComponentAction = Instance1ParentAction | Instance2ParentAction;
And the most important thing of this technique - parent reducer:
function parentComponentReducer(state: ParentComponentState, action: ParentComponentAction): ParentComponentState {
switch (action.type) {
case 'INSTNACE_1_PARENT':
return {
...state,
// using component reducer
instance1: componentReducer(state.instance1, action.payload),
};
//
}
}
Using Discriminated Unions additionally gives type safety for parent and child reducers.
In angular fire documentation, here are the two line I am trying to understand:
// To make the data available in the DOM, assign it to $scope
$scope.data = obj;
// For three-way data bindings, bind it to the scope instead
obj.$bindTo($scope, "data");
Are they doing the same thing? Do both bind to scope for 3 way data binding?
Nope, they're not doing the same thing. That would be a pretty silly API. :-)
Running $scope.data = $firebaseObject(ref) binds the data in the Firebase location to the scope. Any update to the data in the Firebase database, will automatically be reflected in the scope and thus - if you bind an HTML element to $scope.data - also be updated on screen. The flow is uni-directional: from the database, to the screen.
Calling obj.$bindTo($scope, "data") both binds the data in the Firebase location to the scope and listens to changes to $scope.data that it then send back to the Firebase database automatically. So this creates a bi-directional, three-way binding. Updates in the HTML are sent to the database, updates to the database are sent to the screen.
This is all pretty well documented, for example in this blog post "Three-Way Data Binding with Firebase and Angular". The regular AngularFire documentation also contains a good section about three-way data binding.
I am familiar with bindings with curly braces, like {{variable}}, from Polymer 0.5.
However, in examples and code snippets for the release version of Polymer, I've begun to notice bindings with square brackets, such as [[variable]], as well.
Does {{variable}} mean something different now, or is it the same and [[variable]] is just an addition? What is the difference between binding to [[variable]] and {{variable}} in Polymer?
Just as you've noticed, there are now two different syntaxes for data-binding, which have different purposes:
{{variable}} indicates that you would like Polymer to automatically detect whether or not the binding should be one-way or two-way.
[[variable]] indicates that you want the binding to one-way only.
Why the change?
Polymer 1.x differs from older versions is that bindings are now one-way by default, much unlike 0.5, where they were always two-way.
In other words, if you write
<my-element some-property="{{myVariable}}"></my-element>
then by default, when
myVariable is changed, Polymer updates the binding, and thus updates my-element's someProperty.
someProperty is changed, Polymer does not update the binding to myVariable.
This is always the case unless you set notify:true on the property inside my-element:
Polymer({
is: 'my-element',
properties: {
someProperty: {
notify: true,
...
With notify: true, the binding is now two-way, so when
myVariable is changed, Polymer updates the binding to someProperty.
someProperty is changed, Polymer also updates the binding to myVariable.
This behaviour (when using notify: true) used to be default in 0.5; now you must ask for it explicitly.
When to use [[variable]]
There's no technical reason why you must use [[variable]], because Polymer will automatically detect whether bindings are one or two-way with {{variable}}. So why would you use it?
Let's say you're working in a large project, and you know that based on the way that data flows in a particular page/element, a certain property should never be changed by the element it is being bound to, for example in the case of an element which functionally serves a purpose as a label:
<display-data source-data="{{data}}"></display-data>
...
<data-editor source-data="{{data}}"></data-editor>
Everything looks good! The data property is bound to both the display-data element and data-editor elements, and will be automatically shared between them. (In this example, assume display-data's sole purpose is to preview the data that it is bound to.)
One day, you or someone else is editing display-data, and you forget about the situation in which it is being used in above. For an entirely different use-case, you or the other developer would like display-data to also format or otherwise modify the data it is given and push it back towards any other elements that may be bound to it. You/they edit display-data as such:
Add notify: true to sourceData, to allow two-way data-binding.
Add code into display-data which modifies the sourceData property.
This works great for all the pages that needed this functionality. But on the page mentioned before, this was not intended and ends up garbling the data that data-editor sees!
This problem would have been avoided had:
The dev team communicated better and had been more considerate of where elements are being used,
and/or [[data]] was used instead of {{data}} in the page/element in question.
With
<display-data source-data="[[data]]"></display-data>
...
<data-editor source-data="{{data}}"></data-editor>
data-editor can change data, but display-data will only ever be able to read data, and won't be able to change its value when it changes the value of its sourceData property, even when notify: true is set on sourceData.
Therefore, it could potentially be a good idea to:
Use [[variable]] whenever you need to bind to variable. This way, you enforce the direction through which data should flow in your element/page/application.
Use {{variable}} whenever you know that the binding must be two-way.
According to the documentation,
To make your code more easier to read, you may want to use the [[property]] form by default, and only use {{property}} for two-way bindings.
This being said, however, it ultimately comes down to a matter of choice. If you want to forego the use of [[variable]], no one is stopping you and you will not start any fires.
Loving Rivets.js for it's power yet simplicity. However, how to define formatters that take a view-property and format it to a model-property? To my understanding Formatters are meant to operate the other way around, i.e.: from Model to view.
Are View to Model formatters supported somehow, or does this have to be hacked?
This is a feature that was brought in to Rivets.js 0.4.2. Big thanks to GMFlash and mdekmetzian on GitHub for implementing it.
Basically you just define bidirectional formatters as an object instead of a single function. When a formatter is defined as a single function, Rivets assumes it to be in the read direction only. When a formatter is defined as an object, Rivets uses it's read and publish functions to effectively serialize and de-serialize a value.
rivets.formatters.date = {
read: function(value) {
return value.format("DD/MM/YYYY")
},
publish: function(value) {
return moment(value, "DD/MM/YYYY")
}
}
You can also chain bidirectional formatters with any other formatters, and in any order. They read from left to right, and publish from right to left (skipping any read-only formatters when publishing the value back to the model).
Apologies for the lacking documentation. The homepage doesn't reflect at all the current feature set of Rivets.js and needs to be updated to include added features such as this.
I am using Binding IsAsync property to keep UI responsive and loading data from the get accessor of the property and proved to be a good option while using MVVM. This approach is great and doesn't need any manual code for async operations. There are few instances where my dataload is taking few seconds and during this time it is very difficult to differentiate between "no data" vs "data loading". Is there a property which I can detect the state of the binding "IsBusy" or "Loading", so that I can show some message that the loading operation is not complete?
Any help is appreciated.
I know, its an old thread. But if anybody is still interested...
You could use PriorityBinding, there is a superbly explained example in this article:
http://www.switchonthecode.com/tutorials/wpf-tutorial-priority-bindings
The idea is to stipulate a PriorityBinding which in turn defines several regular bindings like this:
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Text>
<PriorityBinding>
<Binding ElementName="MainWindow" Path="Slow" IsAsync="True" />
<Binding ElementName="MainWindow" Path="Fast" />
</PriorityBinding>
</TextBlock.Text>
</TextBlock>
The order of the bindings decides the priority, with the highest priority first. In this case the Fast binding (lowest priority) will populate the textblock immediately because you might have that bound to a string property "Loading..." or "Sorting..." depending on what is happening at the time, and there is no delay.
But later when the slow async binding's property returns a value, it's higher priority means it will then take over, since it is earlier in the list, and its results will be bound instead, showing actual results.
If you need to populate a progress popup you may be able to implement that in the getter of the bound property in your ViewModel, though I haven't tried anything like this.
According to the docs,
While waiting for the value to arrive, the binding reports the FallbackValue, if one is available, or the default value of the binding target property.
You can use this value to display a message to the user while the binding is loading.