I'm having issues accessing input values within my component. I'm trying to dynamically create value bindings in my templates and accessing in the conponent.js file using this.controller.get("pst"+id) however the result is underfined. Using Ember 2.2
{{#each post in |pst idx|}}
{{input value=(concat 'pst' idx)}}
{{/each}}
Well, it works as expected, but why would you want to do this?
Please explain what you want to archive and then we can help better.
And to be clear, a value generated with the get helper is immutable.
Why not do something like {{input value=pst}}?
If this is not an option probably you should build your array in JS and use that then in handlebars!
Define a computed property that wraps your 'post' variable in your component.js file. Iterate over that wrapper. I think this is a powerful way of generating dynamic values.
Your template:
{{#each postWrappers as postWrapper}}
{{input value=postWrapper.value}}
{{/each}}
Your component.js:
postWrappers : Ember.computed('post', function() {
//your concat code
});
Related
I am using Meteor and tried to use #each, but I have a problem with it. I have some values stored in a var like:
var a = [465,77987,2132,2];
I wanted to render each value of a on HTML. I thought #each would be the right way to do it? Actually I don´t know how to use #each and the docs I found don´t really help me. I have written the following code:
JS:
Template.page.helpers({
values: function() {
return a;
}
});
HTML:
{{#each values}}
{{> page}}
{{/each}}
But this is obviously wrong, because I get the this Error in the client console:
Error: {{#each}} currently only accepts arrays, cursors or falsey values.
I thought it is an array or not?
Update
So now I have used the #each in approach, however I still get the same error-message:
Error: {{#each}} currently only accepts arrays, cursors or falsey
values. at badSequenceError (observe-sequence.js:183) at
observe-sequence.js:148 at Object.Tracker.nonreactive (tracker.js:631)
at observe-sequence.js:125 at Tracker.Computation._compute
(tracker.js:339) at Tracker.Computation._recompute (tracker.js:358) at
Object.Tracker._runFlush (tracker.js:523) at onGlobalMessage
(meteor.js:401)
JS:
Template.page.helpers({
values: function() {
var a = [465,77987,2132,2]
return a;
}
});
HTML:
{{#each a in values }}
{{> a}}
{{/each}}
Update 2
I know now where this error comes from. I'm sorry, actually my first post was not correct. I forgot, that these values [465,77987,2132,2] are not directly stored in var a.
They are stored in a Session-Variable and var a = Session.get('values') and I think that´s the point why I get this error...So, I don´t think that this can work with #each ? Maybe I have to save it to my MongoDB first and than render it on the HTML or something like that.
try the each/in construct:
{{#each value in values}}
{{value}}
{{/each}}
c.f. http://blazejs.org/guide/spacebars.html#Each-in
you specified the entire template inside the each, which is what it was complaining about.
I'll put all the code in an example. Consider the 'import' only if you are using the recommended application structure. The files must be in the same directory. First in page.js:
import './page.html';
Template.page.helpers({
values: function() {
var a = [465,77987,2132,2];
return a;
}
});
Second in page.html:
<template name="page">
{{#each a in values}}
{{a}}
{{/each}}
</template>
How can I call inside a helper the equivalent to the Handlebars's helper {{component 'componentName' model=model}} to dynamically render components based on a programmatically changed componentName?
I'm using ember-cli 1.13.8, with Ember 2.0.1.
A bit of context
I have components called cs-widget-image, cs-widget-text, cs-widget-form that expect for a model widget based on its kind attribute.
So for a widget which its kind is image, I wanna render the component cs-widget-image, but I don't think that the logic to discover the name of the correct component should be knew by the model, so I'm not considering using the helper {{component widget.componentName}} on my view.
I think that the better would be have a helper that I can use on my views like:
{{#each manyTypesWidgets as |widget|}}
{{widget-component widget.type model=widget}}
{{/each}}
On my mind, the helper widget-component would receive a widget model, and based on its attributes do a kind of "eval" and internally call the equivalent to {{component 'componentName' model=widget}}
Ex.: With widget = {id: 1, type: 'image'}
{{widget-component widget.type model=widget}}
should programmatically call the equivalent to HandleBars helper on template:
{{component 'cs-widget-image' model=widget}}
Disclaimer about a possible duplicate question
Before mark it as duplicate, I need to say that I really found some similar questions here on StackOverflow like:
[1]
[2]
[3]
[4]
[5], but all the answers are based on an elderly version of Ember that didn't work anymore on Ember 2.0.1 and ember-cli 1.13.8.
You can build a helper and put the logic of building the component name inside of it. Let's call the helper widget-name, you'd use it like this:
{{component (widget-name widget) model=widget}}
If the logic is as simple as appending the widget type to the end of cs-widget- the following should do the trick:
{{component (concat "cs-widget-" widget.type) model=widget}}
I believe your widget-component approach is more complex, because you would have to have a computed property with the logic and then bind that in a {{component call. I hope the two suggestions are helpful :)
Won't this work for you?
//JS
widgetsWithTemplates : Ember.computed.map('manyTypesWidgets', function(widget) {
widget.set('componentName', 'cs-widget-' + widget.get('type'));
})
And in the template you just call the component by componentName property:
//HBS
{{#each manyTypesWidgets as |widget|}}
{{widget.componentName model=widget}}
{{/each}}
I often find myself dividing my work into templates that still could use the same helpers.
So, say I have this template structure:
<template name="MainTemplate">
<div>{{> FirstTemplate}}</div>
<div>{{> SecondTemplate}}</div>
<div>{{> ThirdTemplate}}</div>
<div>{{> FourthTemplate}}</div>
</template>
Now each of these templates wants to use the same helper, let's call it dataHelper:
Template.MainTemplate.helpers({
dataHelper: function() {
//do some stuff
return result
}
})
Sadly, this helper can't be accessed in template first through fourth by simply typing {{dataHelper}} like how events work.
My solution has been to create a global helper instead, but that seems a tad overkill, especially since I have a few pages that don't care about these helpers at all. Another solution is to create four separate helpers but, hey, DRY.
Am I missing something simple here?
There isn't an obvious way to do this in the current version of meteor. One solution is for the child template to "inherit" the helpers from the parent. You can do this pretty easily using meteor-template-extension. Here's an example:
html
<body>
{{> parent}}
</body>
<template name="parent">
<h1>parent</h1>
{{> child}}
</template>
<template name="child">
<h2>child</h2>
<p>{{saySomething}}</p>
</template>
js
Template.parent.helpers({
saySomething: function() {
return Random.choice(['hello', 'dude!', 'i know right?']);
}
});
Template.child.inheritsHelpersFrom('parent');
The template child inherits all of its parent's helpers so it has direct access to saySomething.
This technique has two drawbacks:
you have to specify the inheritsHelpersFrom relationship
all of the parent's helpers are inherited
You can access your parent helpers using either a notation like {{yourParentHelper ..}} with two dots. Have a look here for more informations (end of the article)
You can also access parent data context in javascript like that:
var parent_data = Template.parentData();
By the way, you can add a parameter to reach the third parent, for instance:
var parent_data = Template.parentData(3);
The double dot notation seems to work best within {{#each}} loops, and I'm not having any luck within actual child templates. One option would be to use {{#with}}, although that limits you to basically one helper. e.g.:
<template name="parent">
{{#with dataHelper}}
{{> first}}
{{> second}}
{{/with}}
</template>
This will set the data context of the child helpers to dataHelper, and you can access them with {{this}} inside the template. I suppose you could make dataHelper an object and then pass in multiple pieces of data that way.
Just trying something but not sure how to do it.
Scenario:- I'm trying to render a page which have a configuration data and view data, so basically My template loop on the configuration data to render page and fetch value from view data to display.
so my model have something like
model:{'confData':[{'displayName':'value1','fieldName':'Field1'},
{repeat similar object}
],
'viewData':{'Field1':'value1','Field2':'value2',....}
}
Now in template I'm trying to render like:
{{#each confData}}
this.displayName {{input type='text' value=viewData[this.fieldName] }}
{{/each}}
but it does not accept it. Any suggestion on how I can deal with this sort of problem.
PS: the confdata and view data in actual application will be api call which i can't change.
I saw somthing like http://jsfiddle.net/GRaa5/4/ but when I tried changing as http://jsfiddle.net/weyzay5v/ it failed.
Thanks.
There is no way to do what you want purely with Handlebars. Remember that Handlebars templates are logic-less and for presentation only. My suggestion would be to make a computed property in your controller:
data: function() {
var confData = this.get('confData');
var viewData = this.get('viewData');
return confData.map(function(data) {
return {
displayName: data.displayName,
value: viewData[data.filedName]
};
});
}.property('confData.[]', 'viewData')
Then in your template:
{{#each data}}
{{displayName}} {{input type='text' value=value}}
{{/each}}
The documentation has an example of using an ArrayController with this template:
{{#each MyApp.listController}}
{{firstName}} {{lastName}}
{{/each}}
This is how the ArrayController is used:
MyApp.listController = Ember.ArrayController.create();
$.get('people.json', function(data) {
MyApp.listController.set('content', data);
});
How would this work differently than using a plain array like this instead?
MyApp.listController = [];
$.get('people.json', function(data) {
MyApp.set('listController', data);
});
If you don't need the behavior of a controller, you can use a plain array.
An ArrayController wraps an array, with some other properties added, such as the sortable mixin.
You can see it here:
https://github.com/emberjs/ember.js/blob/master/packages/ember-runtime/lib/controllers/array_controller.js
in the ember.js documentation says:
(http://docs.emberjs.com/symbols/Ember.ArrayController.html)
The advantage of using an ArrayController is that you only have to set
up your view bindings once; to change what's displayed, simply swap
out the content property on the controller.
it uses an Array in background, only helps with methods to work with the array:
Although you are binding to the controller, the behavior of this
controller is to pass through any methods or properties to the
underlying array