emberjs bind data attributes - ember.js

I am wondering if there is a way to bind data attributes in a template when calling a view.
For example (this doesn't work):
{{ view App.SomeView data-dateBinding="currentDate" }}
I have ended up doing it this way:
<a {{bindAttr data-date="currentDate"}}></a>
There must be a way to do it when calling the view?

More on the excellent answer from #kurt-ruppel.
An example using : to describe the property for attribute binding, entirely done from the view.
App.SomeView = Ember.View.extend({
attributeBindings: ["date:data-date"],
date: function() { return '1642-12-06' }
.... rest of view
})
The cleaner template.
{{view App.SomeView}}

You have to define in App.SomeView which attributes you want put in the HTML.
App.SomeView = Ember.View.extend({
attributeBindings: ["data-date"]
.... rest of view
})
Now data-dateBinding should work:
{{view App.SomeView data-dateBinding="currentDate" }}

FWIW - and this is in response to #sly7_7's comments from the top answer -, it is possible to specify a data-* attribute binding in the view itself, as opposed to setting it in the template.
Similar to classNameBindings, you can prepend a preferred value to the attribute, joining the values with a ':'. Best place to see this in action is probably in the related ember.js tests. Gives credence to the value of good testing, seeing as how sometimes it serves as the best documentation.

Related

Accessing model data in router when using a view

I am looking for a way to access model data in a route when using a view to display model attributes.
Example
Template
<h2>New post</h2>
<form {{action save model on="submit"}}>
<label>Title</label>
{{input type="text" value=title placeholder="title" id="title"}}
<label>Text</label>
{{view "tinymce" value=text }}
<button>Post</button>
</form>
View Template
<textarea id="tinymce">
</textarea>
View
export default Ember.View.extend({
templateName: 'views/tinymce-textarea',
didInsertElement: function() {
tinymce.EditorManager.execCommand('mceRemoveEditor',true, 'tinymce');
tinymce.EditorManager.execCommand('mceAddEditor',true, 'tinymce');
}
});
Router
export default Ember.Route.extend({
....
actions : {
save : function(model) {
if (!model.get('title').trim() || !model.get('text').trim()) {
return;
}
model.save().then(this.onSuccessfulSave.bind(this), this.onFailedSave.bind(this));
}
}
});
Now, obviously this doesn't work, since model.text is never bound in the view, like it would be if I were to use the textarea template helper:
{{textarea value=text placeholder="text" id="text"}}
But this is just one of many (many) ways I have tried to get this to work, and I am at a complete loss as how one would access model attributes in the route when using a view. And it does seem like a pretty common usecase to me too.
I have failed to find information regarding this on SO or anywhere else, so if anyone is able to help me, thanks in advance! / AS.
So one of the main things that you're missing out is binding the view to the controller. This is actually really straight forward to do, but without it Ember doesn't know that it should propagate changes between the two. The first thing I would do is this:
{{view "tinymce" valueBinding="text" }}
This says that the views value will be binded to the controller's text value. Whenever view's value is updated, it will propogate to the controller and vice versa.
The next item to take care of is actually binding the value in the view. All you need to do is tell the input to bind it's value to the view's value. This can be done like this
{{textarea value="view.value" placeholder="text" id="text"}}
Try this out, and you can use this jsbin that I created as an example:
http://emberjs.jsbin.com/qanudu/26/
If you have any other questions just let me know, but this should solve your issues!

Access to controller's param in Ember view

Let's say I have IndexController and it has a param called isEditing.
I also have index template which {{render list}} template.
I have a problem in using isEditing property in list.
You can find an example here http://emberjs.jsbin.com/kabumuca/1/edit
Did I miss something here?
Ahoy!
So, here is the working jsbin: http://emberjs.jsbin.com/kabumuca/9/edit.
Essentially, the reason why it wasn't working was because of a misinterpretation of the view helpers. When you're using the {{render}} helper, it ties your controller to the view you are rendering. As you weren't specifying a literal view (just the template and model), it was creating virtual view and controller for you.
See here: The Render Helper - Ember.js
This might help
App.ListController = Ember.Controller.extend({
isEditing: Ember.computed.alias('parentController.isEditing')
});

How to render a nested view (relative view)

I have the following (ember-1.4.0):
App.DateRangeSelectorView = Ember.View.extend({
templateName: 'date-range-selector',
selectedBinding: 'controller.selected',
dateRangeSelectorItemView: Ember.View.extend({
tagName: 'li',
classNameBindings: ['isActive:active'],
isActive: function() {
return this.get('item') === this.get('parentView.selected');
}.property('item', 'parentView.selected')
})
});
And the template:
<script type="text/x-handlebars" data-template-name="date-range-selector">
<ul class="nav nav-pills" style="margin-bottom: 10px;">
{{#view view.dateRangeSelectorItemView item="today"}}
<a href="#" {{action gotoToday}} >{{controller.content.today.label}}</a>
{{/view}}
....
</ul>
</script>
I have followed the guidelines specified here, specially:
When nesting a view class like this, make sure to use a lowercase
letter, as Ember will interpret a property with a capital letter as a
global property.
Thanks, but no thanks: ember is stubbornly saying:
Uncaught Error: Assertion Failed: Unable to find view at path 'view.dateRangeSelectorItemView'
I have tried with and without the view. prefix, but no luck. How can I render the nested view?
EDIT
The problem seems to be that the lookup performed by the container is failing. Maybe there are some capitalization or name coercion rules that I am not getting right. I would like to list all available views, so that I can recognize if my view is there, maybe with a slightly different name.
How can I list all available (registered?) views, including nested views? That would include dateRangeSelectorItemView, which is a view nested inside App.DateRangeSelectorView, and is not defined in the application itself.
I guess what I am looking for is a way of listing all objects (with their lookup names!) which are extensions of Ember.View: Ember.View.extend()
The problem is that I was using an outlet for this, and the outlet does not allow to specify a view: it generates the view according to the template name, so that my DateRangeSelectorView was not used. I have raised an issue about this.

Custom Handlebars block helper

How do I define a custom block helper in Handlebars (for use with Ember.js)? I've tried using the method described on the Handlebars site, but it doesn't seem to work. I get this error from Ember.js:
Assertion failed: registerBoundHelper-generated helpers do not support use with Handlebars blocks.
Here's the code for my helper. The idea is that the block will only be rendered if the models that I pass in are the same:
Ember.Handlebars.helper 'sameModel', (model1, model2, options) ->
if model1 is model2
new Handlebars.SafeString(options.fn(this))
else
''
6 months later, it looks like this is possible now, at least to a certain extent. You can view the discussion here. I agree with the pull request that this should usually be handled using computed properties, but this is still very useful in some cases.
I'm going to accept this answer to keep this post updated. If I've broken any SO etiquette, let me know. :)
Assertion is correct. You cannot do that, at least not it RC6 and before.
You may want to create a view with a template and bind some properties to it:
some.hbs
{{#if model1}}
This is model1 {{model1.name}}
{{/if}}
{{#if model2}}
This is model2 {{model2.name}}
{{/if}}
views/some.js
App.SomeView = Ember.View.Extend({
templateName: "some"
})
different template
<h3>{{view App.SomeView model1Binding=someModel1 model2Binding=someModel2}}</h3>

Ember JS/Handlebars view helper

Currently, if we define our view as {{#view App.myView}}, ember/handlebars will wrap the view element inside a <div id="ember-1234" class='ember-view'>.
Is there a way to stop this?
You probably want to set tagName as ''.
App.MyView = Em.View.extend({
tagName: ''
});
At least it stops wrapping inner contents.
If you want to customize view element's id, you can use:
{{#view App.myView id="my-id"}}
I usually think my views as wrapper. For example, if the initial given html code is :
<div class="item"><p>my stuff></p></div>
Then I create a view with a tagName property as "div" (which is default), and classNames property as "item". This will render, with proper handlebars template :
{#view App.myView}
<p>my stuff></p>
{/view}
-> render as
<div id="ember-1234" class="ember-view item">
<p>my stuff></p>
</div>
Then if you need to have your proper ID on this div, you could define the "elementId" property on your view class (before create()). (#see source code)
I assume you are talking about the 'ember-view' class which is not customizable (element type being customizable thanks to the tagName attribute...).
Actually, Ember later uses this class to register (once!) an event listener on the document in order to dispatch events to the JS view.
I don't mind it would be that simpler to avoid using this class. There would have to find another way to select all ember's controlled element, but I have no idea how.
See source, # line 117.
If I understand you correctly you want to achieve something like jQuery's replaceWith? You can use this in Ember.js when my Pull Request gets merged: https://github.com/emberjs/ember.js/pull/574.
Also have a look at Create Ember View from a jQuery object