Bind TextArea linebreaks to html - ember.js

I have a textarea binded to a div such that anything you type in the textarea updates the div.
The only thing that bindings doesn't respect is newlines in textarea so if you hit 'enter' within textarea, the div doesn't get a break.
Fiddle: http://jsfiddle.net/lifeinafolder/Ajkyw/19/
I am using a helper and it doesn't work.
As per Point 4 on this link: http://codebrief.com/2012/03/eight-ember-dot-js-gotchas-with-workarounds/, it is not supposed to work. But even with the solution on that link, I can't get it to work.
Any ideas on how to update the div with <br/> tags on linebreaks within the textarea?

Use a computed property to format the location's line breaks.
HTML:
<script type="text/x-handlebars">
{{#with App.obj}}
{{view Ember.TextArea valueBinding="location"}}
<div>{{{formattedLocation}}}</div>
{{/with}}
</script>
JavaScript:
App.obj = Ember.Object.create({
location:'Palo Alto',
formattedLocation: function() {
return this.get('location').replace(/\n\r?/g, '<br />');
}.property('location').cacheable()
});
http://jsfiddle.net/e8G2j/
In the example I removed your helper so it would be a bit easier to follow exactly what is going on. If you need to use a helper and are unable to figure it out let me know and I will add the helper back in.

Related

EmberJS: How to position the application template

I'm running into a problem. I need App.rootElement = "body", because views and components will be used all over the place. I do not want to put the entire page in a handlebars template, due to SEO and other concerns. The main application template will exist somewhere in the center of the page:
<h1>Header markup</h1>
<script type="text/x-handlebars">
<h2>Application Template</h2>
{{outlet}}
</script>
<h1>Footer markup</g1>
However, when the page is rendered, this template is appended to the end of the body, instead of staying where the template script has been placed. (see jsbin exmaple) Is there any way to tell Ember to render the application template where it is in the markup?
One hacky solution I've found is to manually move the containing element in didInsertElement, but that seems a little heavy handed and not something that would be considered a best practice. (see jsbin example)
The script tag doesn't have anything to do with placement, if you want it to live somewhere create a div tag, id it, and change the rootElement to that div tag.
<script type="text/x-handlebars">
<h2>Application Template</h2>
{{outlet}}
</script>
...
<h1>Header markup</h1>
<div id='foo'></div>
<h1>Footer markup</h1>
App.rootElement = '#foo';

Updating partial style content

I would like to do the following handlebar script:
The color:{{object.labelColor}} seems not working (Cf. other post).
One solution seems to bind the complete style attribute on the "javascript side" but I would like to avoid managing the "fixed" part of the style (text-align:left) on that side.
Is there a solution to make something similar to my sample code (dynamic part on the js side,fixed part on the html view) ?
<div class="label" style="color:{{object.labelColor}};text-align:left">{{object.name}}</div>
You could use 'classNameBindings', and define a set of css rules to the corresponding classes.
Js
Ember.View.create({
classNameBindings: ['isUrgent'] // array of class names
isUrgent: true //conditional to set class name
});
css
.is-urgent{
background-color: #356aa0;
}
Resource
http://emberjs.com/api/classes/Ember.ContainerView.html#property_classNameBindings
If you have to use styles instead of classes, and want to change only a portion of the style strings at the time, one alternative would be using $.css, applying the style changes you want. For example:
<script type="text/x-handlebars">
<h1>App</h1>
{{view App.SomeView}}
</script>
<script type="text/x-handlebars" data-template-name="some-view">
<div style="color:#00F;text-align:left">
Some View<br />
<button {{action changeColor on="click"}}>Change Color</button>
</div>
</script>
<script type="text/javascript">
App = Em.Application.create();
App.SomeView = Em.View.extend({
templateName: 'some-view',
changeColor: function(e) {
console.log('changing color');
this.$('div').css('color', '#F00');
}
});
</script>
In the script above I'm using jQuery's css function to change the color attribute whatever elements my selector returns from within SomeView instance (in this case as I only have one div, I'm using the element as a selector). There are other (and likely better) ways to do this, but I hope this helps.
The problem with this solution as it is, is that you can't keep the state of the style attribute as it's not bound to any property, that's why I think binding classes would be better in the long run.

Getting the content rendered inside a #each ember template helper, without the #each content binding

/START description of why
I'm doing a 'load more' type of interaction: user gets at bottom of a page, I load more content.
As I'm using a plugin that formats content in a 'pinterest-style' (masonry), I need to take the output of a rest call, formatted using an ember view, and i'm doing something like:
<div id="list">
</div>
<div id="hidden" style="display:none">
{{#each item in App.itemsController}}
test {{item.id}}
<br />
{{/each}}
</div>
What I want to do is, load the content in the hidden div, and then pass its HTML generated content to the plugin to process in my formatted list view.
If I just copy the #hidden content, the Ember scripts get in, and on subsequent 'load more', content is inserted in the #list, in addition of going in the #hidden div.
That's because I copied the entire handlebars.
So I get rid of the container tag, the one I supposed was wrapping the controller content binding, but even when stripping it from the content I pass to #list, the #list still auto-updates when a 'load more' is called.
I know that's a dirty hackish thing, but in order to improve performance in the client I must take a similar route.
/END description of why
//ACTUAL QUESTION ;)
Given this background, the question is, stripping the container metamorph script tags (like the ones here below), and just take the content inside them, shouldn't get rid of the auto-updating content functionality?
<script id="metamorph-X-start" type="text/x-placeholder"></script>
//ALL THE CONTENT
<script id="metamorph-X-end" type="text/x-placeholder"></script>
Inside those, I just have the actual content generated, like:
<script id="metamorph-9-start" type="text/x-placeholder"></script>
test <script id="metamorph-59-start" type="text/x-placeholder"></script>2873<script id="metamorph-59-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-9-end" type="text/x-placeholder"></script>
<script id="metamorph-10-start" type="text/x-placeholder"></script>
test <script id="metamorph-60-start" type="text/x-placeholder"></script>2872<script id="metamorph-60-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-10-end" type="text/x-placeholder"></script>
The alternative is programmatically render the template inside a variable and process that, which is surely a better way of doing this, but I just wonder how the #each binding works internally as I thought the metamorph was doing that.
Have you looked into using a CollectionView and calling the plugin through the didInsertElement callback?
e.g.
MyList = Ember.CollectionView.extend({
itemViewClass: 'App.ListItem',
didInsertElement: function(){
view.$().jqueryPlugin({ ... })
}
})

Using Ember.js text field ids for a <label> tag

A label tag is of the form:
<label for="id_of_text_field">
<input type="text" name="example" id="id_of_text_field" />
Where the for tag of the label and the id tag of the text field need to match. I had two ideas to make this work in my Ember.js template:
Idea #1: I tried to make a special binding named field_id to use in both the label and the TextField. I executed this as follows:
<label {{bindAttr for="content.field_id"}}> {{content.label}}</label>
{{view Ember.TextField valueBinding="content.data" id="content.field_id"}}
Unfortunately only the label's id renders correctly. The TextField's id does not render correctly and turns out to be "metemorph... something-or-other".
Idea #2: To somehow conjure the TextField's id and use that for the label tag, but I'm afraid at some point the TextField's id will not be ready when the label tag is rendered. Even if this were not an issue, I do not know how to find the TextField's id from JS.
This is in a template so I will have more than one of these label/TextField pairs.
How can I get the label's for tag to match up with the TextField's id tag with Ember.js?
Thank you!
UPDATE
Using Peter Wagenet's advice and slight modification, I did the following:
<label {{bindAttr for="textField.elementId"}}> {{content.label}}</label>
{{view Ember.TextField valueBinding="content.value" viewName="textField"}}
Using this technique users can now click labels to select TextFields, CheckBoxes, and Selects.
First off, the Metamorph tag is for the label's value. It's not related to the field's id. However, this code still won't work because standard properties don't do anything special with property paths. In this case, the value of id, is literally content.field_id. This is certainly not what you wanted. In normal circumstances, you could use elementIdBinding (id is just an alias for elementId), however the element ids for Ember Views cannot be changed after creation so that approach won't work here.
One possible solution makes use of the viewName property. The viewName property provides a named reference to the view on the parentView. You could then, do the following:
<label {{bindAttr for="view.textField.field_id"}}> {{content.label}}</label>
{{view Ember.TextField valueBinding="content.data" viewName="textField"}}
This won't always solve your problem, but I just wanted to add that simply nesting the input inside the label is often a convenient solution, since it allows you to drop the for attribute altogether (reference).
Here was my solution to this problem from a while back:
App.Widget.TextField = Em.ContainerView.extend({
tagName: '',
type: 'text',
label: null,
value: null,
valueSize: '30px',
childViews: ['labelView', 'inputView'],
labelView: Em.View.extend({
tagName: 'label',
attributeBindings: ['for'],
forBinding: 'parentView.inputView.elementId',
init: function () {
this.set('defaultTemplate', Em.Handlebars.compile(this.getPath('parentView.label')));
this._super();
}
}),
inputView: Em.TextField.extend({
typeBinding: 'parentView.type',
sizeBinding: 'parentView.valueSize',
valueBinding: 'parentView.value'
})
});
Then from within a Handlebars template:
{{view App.Widget.TextField label="Some Label"}}

how can i unbind an emberjs handlebar helper

I have a custom handlebar helper:
Handlebars.registerHelper('foo', function(key) {
return (key + ' bar');
});
and in my html I have:
{{foo beer}}
the result is
<div id="ember127" class="ember-view">beer bar</div>
how can I make my own handlebar helper act like the ember {{unbound beer}} and just produce "beer bar" without any additional markup ?
So I think you might be confused on how the helpers, templates, and Ember views work exactly. The markup you created is expected and is the exact markup you'd get with a working unbound helper.
Ember.Handlebars templates are always placed within an Ember view object (as you have above). Something that a normal bound helper would produce would be:
<div id="ember127" class="ember-view">
<script id="metamorph-1-start" type="text/x-placeholder"></script>
beer bar
<script id="metamorph-1-end" type="text/x-placeholder"></script>
</div>
Now if you want to surround your string with some other tag than a div (lets say an anchor tag or something), then you'd need to create a view, set it's template and tag name, then append that view.
Take a look at this jsFiddle and take a look at the results pane in your inspector for some examples of what I'm talking about. Hope that clears things up for you.
Ember has a helper called unbound that lets you wrap another helper. You can thus turn your bound (automatically) foo helper into an unbound one like so
{{unbound foo beer}}