Closed mcartmel closed 9 years ago
No - you can't use that syntax in JsViews if you want the automatic observable data-linking behavior to work. JsView data-linking expressions bind to objects based on path expressions, a.b.c
with variants like a.^b.c
(which will listen to changes of both the leaf property, a.b.c
and the object a.b
, but will not listen to changes in the object a
- see 'Deep paths': http://www.jsviews.com/#observe).
I don't believe the overhead in code, perf cost, and complexity of supporting live data-linking to a['b']['c']
would be justified.
So it means you have to map your objects to new ones which limit the property names to the allowed character set: valid JavaScript name characters (a-z, A-Z, 0-9, _, $) - in particular, for any properties which you need to be dynamically linked.
So this should be fine {{:#data['var-with.dots.and-minus']}}
(not data-linked).
But {^{:#data['var-with.dots.and-minus']}}'
and data-link="{{:#data['var-with.dots.and-minus']}}"
will not listen to updates in that property...
Closing, since question answered.
What about the case where you want to generate the property names dynamically?
For instance, you could filter the property names using a helper function that returns an array of property names. Then you might like to show textboxes bound to those properties only.
Your only option is to compose the property name in a string and access it through the array braces. But this is not working two-way. It does not update the underlying property.
I am talking about valid variable names.
I solved this by getting the value of the data-link attribute dynamically as a string using another helper function, where I made the string to use the correct variable name.
I am certainly terrified this worked. Those things one day will conquer the world :smile_cat:
@larjohn: Ok good.
If you want, you could create a jsfiddle showing what you did. I'd be interested to see it. And then if I have alternative suggestions/ideas, I'll let you know.
@larjohn: I just created a jsfiddle which lets you choose a property/field of an object and dynamically associate it as data-link target for some inputs.
On 09/28/2015 09:10 PM, Boris Moore wrote:
@larjohn: I just created a jsfiddle which lets you choose a property/field of an object and dynamically associate it as data-link target for some inputs.
i am afraid that the very requirement of dynamic data-linking testify for a bad application design (most likely bad data design)
@eugene-panferov yes it is a bad data design. I have a judgment object which instead of having an array with 20 fact strings, it has fact1, fact2, fact3 ... fact20. I can't change that. So dynamic property selection allows me to loop an array of 1...20, and create the property name an then access it. I had tried with #data['fact1'] but it didn't work two-way.
I was not aware that you can use the {{}} notation inside the data-link attribute. I hope it works correctly inside a {:}, as I have more than one attributes linked in that element.
I don't have the actual source code available at the moment. What I did was sth like that: data-link="{{:~getTheString()}}" where getTheString returns the whole string with judgment.fact1...fact2 notation in-place. Nothing as fancy as what Boris suggested.
@eugene-panferov - Well often, I agree, it may be the result of bad design. But I'm not sure if one can say that is always so. For example these examples http://www.jsviews.com/#samples/editable all let the user select an item and then provide editing UI - master/detail style.
So they include {^{for movies[selectedIndex]}}
- which dynamically binds to a different item when selectedIndex changes. Of course the data-link expression itself is not modified. Similarly JsViews will work with this as two-way binding:
<input data-link="movies[selectedIndex].title" />
If you do the similar thing where movie has properties which have object values, each with a title property, then this will also work:
<input data-link="movie[selectedProperty].title" />
If the properties are strings and you want one-way binding, this will work too:
<input data-link="{:movie[selectedProperty]}" />
But if they are strings and you want two-way binding, then it will not work. JsViews doesn't know how to dynamically bind back to a different property when selectedProperty changes. That's the scenario where you could consider the dynamic setting of the data-link expression as in my jsfiddle above.
@larjohn - my use of {{}} inside a data-link attribute data-link="object.{{:selected}}
will initialize the data-link - as will yours data-link="{{:~getTheString()}}"
- but I did not write data-link="data-link="object.{^{:selected}}
- that will give you a syntax error. So for updating I am unlinking and relinking to the new expression, from code... I'm not sure how yours is working if the results of getTheString() are supposed to change dynamically. Perhaps in your scenario you don't need that - and the initial static values remain valid...
I might add I use this technique extensively for an form based application in which the users defines the fields themselves and therefore it is impossible to know in advance which fields will exist. I am able to do things like:
{^{for fields() }}
{{if type == 'text' }}
<input data-link="{{{:~chooseConvert(#data)}}:{{:bindValue(#data) }} trigger=true :{{chooseConvertBack(#data)}}} />
{{else type == 'picklist'}}
<select data-link="{{{:~chooseConvert()}}:{{:bindValue() }} trigger=true :{{chooseConvertBack()}}}>
{{for options() }}
<option id="{{:id}}">{{:label}}</option>
{{/for}}
</select>
{{else type == 'checkbox'}}
... etc ...
{{/if}}
{{/for}}
I find this invaluable for dynamic user interfaces.
The helper functions all return the 'correct' string for the given context (user / field type / form context etc.)
I data-bind the for loop such that if the user redefines the fields available, all the converters and data-link statements will be reevaluated. If you have such a scope you might be able to do something similar in lieu of manually relinking.
Yes - refreshing the UI from higher up will most often be the best tactic, rather than the 'manual' programmatic unlink/link. This is a related discussion - and touches on that same point: https://github.com/BorisMoore/jsviews/issues/319#issuecomment-143315854.
But for JsViews as a platform, of course, providing some fallback provisions allowing programmatic re-linking is a good feature to provide - but not to encourage overuse of :)
This worked as well:
<select class="chosen-select-withAdd facts-list-trigger"
data-link="name{:'judgements'+ ~j_iterator+'.fact'+#data+'_uns'}
id{:'judgements'+ ~j_iterator +'.fact'+#data}
{:~judgement.{{:'fact'+#data+'_uns'}}:}" >
Please keep maintaining this excellent framework!
@larjohn - good. Yes I will... I am currently working on completing the JsViews documentation, and after that will declare V1.0 for both JsRender and JsViews. Meantime any tweets/blogs etc. to 'spread the news' are always appreciated. Not enough people know about JsViews...
Hi Boris,
Just in reference to this (very old) issue.
I have also been trying to work with property names that have minus characters and/or other special characters.
I can see that it's possible to use #data['var-with.dots.and-minus'] to show these properties, but is it possible to also do data-linking and observable changes? I can't see to make it work.
http://jsfiddle.net/LqscLj60/2/