Ember has a reputation of having a steep learning curve, and though that may be it, what I find online confirms my experience. That experience so far is, that it’s difficult if you want to loop through your model to dynamically build out most of your HTML and let Handlebars write and bind it. As far as I’ve discovered, I’m still stuck with cumbersome JS HTML strings. The simplest example of this is the inability to do…
{{#if model.input.type == ‘select’}}
or, how about passing model values to a helper…
{{#myhelper model[i]}}
or
{{#myhelper model[i].type}}
*I figured this part out. I was confused by Ember.Handlebars vs Handlebars, for the helper method.
…or, returning bound Handlebar expressions, so my helper can return this:
{{input action='myAction}}
Without those conveniences, life is pretty difficult as I have to loop through the model and compile my HTML string. So, I’d like to suggest the following:
I agree that not being able to do something like this, can be annoying at times. Even though many may say you “should” keep this logic out of your views/templates.
I did try that route, but because you can only pass in literals and not values, it didn’t help me. If the {{#blocks}} would resolve the model values, I could do…
{{#myhelper model.type}}// resolve to ‘select’
…and test the string value in the helper to build out the correct HTML. Ah, but then I run into problems returning bound expressions like so…
{{input type=model.type}}{{action ‘myAction’}}
It may be an issue of design and a separation of concerns, in which case I’ll defer to the experts, but I can’t help questioning the utility of that logic in cases like this.
Thanks, I’ll take another look the components. My first impression was that I would face the same problems there. This JsBin shows what I am going for. If the helper could return compiled and bound Handlebars expressions, I think I’d be home free.
I ran into this same problem with Angular too, [as someone else posted][1]. It looks like their solution is to build a custom [Angular.widget][2], which allows building out the form in the HTML code with a custom directive. The ng-if didn’t work either. Maybe something to do with it creating it’s own scope, so this is meaningless as question is not in scope:
ng-if="question.type == 'checkbox'
it has no awareness of ‘question’, and just returns true.
I’m afraid I haven’t implemented the radio and checkbox components for you but you should get the general idea i.e. you define each of the different types of input that you need as a component and let the loop decide which to use based on the type property of the question.
You may find Ember EasyForm helpful either to use directly or get inspiration from.
Dynamically rendering things is definitely an easy task with ember, and some of the approaches mentioned here will work great. The approach I would probably use to keep this really simple is to wrap each input in an itemController, then use Em.computed.equal macro to determine what to render:
A lot of figuring out ember is figuring out how to build the data structures your template needs, and an item controller is a nice way to do this for templates without manually looping over your data and adding new properties.
Thanks for the tips. I can investigate them after work.
At first glance, it’s not clear where the JSON would get iterated over. Would this approach allow you to dynamically build out a form defined by big blob of JSON?
Yes, the solution I gave above assumes you are iterating over JSON. Although you may need to preprocess your JSON using a computed property in order to make it into the right structure you need.
The each helper in the example is where the json is iterated over. This assumes you have set it to be the model of this template’s controller.
Sitll struggling with this. I don’t see where it compares the question.type to determine which input type to build out. I JSbin’d it, so you can see what I’m after. It should produce 2 checkboxes, 3 radio bottons, and a select DDL. It will also need to iterate over the answers obj to set the attributes and displayed text for each input.
So far it seems the fundamental problem remains; comparing model values on the fly.
I haven’t been able to spend much time testing this out, but I am seeing the same problem, which is resolving the model value in the Render statement. It just comes through as a string. You can see it here
You were pretty close but the critical thing that was missing was the itemController in the each loop. When you specify the itemController each item in the loop receives it’s own new copy of the controller. It’s also important to use an ObjectController rather than the basic Controller so that the controller can receive the item as it’s model.
If you’re referring to the values for the select that’s because you’ve quoted them, if you want to pass a bound value or literal you just omit the quotes i.e.
Yes, thanks! I think this is it. It’s looking really good. It’s producing the output I want, with out too much work, and no cumbersome JS HTML strings. See the Updated JSbin with the radio buttons wired up to an action.
The ability to bring in another separate controller into the template loop provides the comparison logic I was looking for. This provides a lot of flexibility. I’m looking forward to stepping through the code and exploring this further.
Once you start getting the radio, checkboxes etc. wired up you’re probably going to want to introduce a controller for each one, the next step towards that is to break out the individual views, http://emberjs.jsbin.com/suzalosu/1/edit
I want to reuse the template and just pass in a diff model. I got this working at home. The JSbin works in Chrome, but it doesn’t seem to work in FF. I think this seals it; all my big questions have been answered. I’m now pretty enthusiastic about Ember.
If there’s anything catastrophic about doing it this way, I’m all ears.
I don’t think there’s anything wrong with your general approach but personally(and I think this is more idiomatic ember) I’d prefer to break out the components so that you’d have something like: