Ember Checkbox -- Accessing model property from different controller - ember.js

I have a checkbox on a modal popup and need it to be checked based on the value on an unrelated model. The model is Team and the property I need to access is called syncAccount (boolean), so the input helper would likely look something like this:
{{input type="checkbox" name="syncAccount" checked=team.syncAccount }}
How can I access or bind to team.syncAccount from the modal? I have a ModalImportController, but no associated route. Is there some way in this controller I can assign a property that looks up or binds to the value of syncAccount for the current team (and is updated as they toggle it)?
Similarly, I need toggling the checkbox to send an update request for this field. Will this need to be an ajax request, or is there some way to set the model used by the checkbox to point to a team so that I can call #model.save()?

To get access to a property from another controller you first need to include that via needs like so:
App.ModalImportController = Ember.ArrayController.extend({
needs: "team",
teamController: Ember.computed.alias("controllers.team"),
});
then you would have access to it's properties like so:
// still in ModalImportController
syncAccount: function() {
return this.get('teamController.syncAccount');
}.property('teamController.syncAccount')
I haven't tested it now, but that's the way I did it in a slightly different setup.
source:
[http://guides.emberjs.com/v1.13.0/controllers/dependencies-between-controllers/][1]
For toggeling to send an update request I use:
syncAccount: Ember.computed('model.syncAccount', {
get: function() {
return this.get('model.syncAccount');
},
set: function(key, value) {
this.set('model.syncAccount', value);
// do all you need to do via AJAX here
return value;
}
})
note, that you also GET the value from here, so change your input-helper to:
{{input type="checkbox" name="syncAccount" value=syncAccount }}

Related

How to handle ember checkbox binding

I am new with ember and I have a question about checkbox binding.
Here is my js && hbs :
CompletedToday(id){
var today = new Date().toISOString().slice(0, 10);
this.get('DS').findRecord('menu',id).then((recs) => {
recs.get('completedDates').pushObject(today);
recs.save();
});
},
{{#each menu}}
{{input type="checkbox" checked=this.checkCompleteToday click=(action "CompletedToday" menu.id)}}
{{/each}}
Menu is a model has a attribute called Completed date, which is a array contains a list of dates(YYYY-MM-DD), there should be a constructor function to check if it’s completed TODAY, if it is completed, make the checkbox of that menu as checked. If not, user can check the specific checkbox I don’t know how to handle this actually, do i need to create another attribute for menu?
Any suggestion would be appreciated
First you need a computed property that returns true or false if TODAY is in the model.
you should create in your component a computed property like:
checked = computed('model', function() {
// pseudocode bellow
return (TODAY in array)
})
Now, if it is unchecked (TODAY not in array), you should be able to insert in array.
In you hbs:
{{input type="checkbox" checked=checked click=(action "CompletedToday" menu.id)}}
(you shouldn't use "this" to reference the property)
If "CompletedToday" is in your component actions, it should work.
I hope this helps

emberjs add code on the fly, after template render

In emberjs, you can add code to your template file:
{{input type="text" value=color}}
the template then renders. But the question is, how can you add this dynamically after the template renders? For example, I want to add a button, to generate new input fields (colors), and the user can continue to add new colors as needed? How would one go about doing this?
First of all, if you want to let user add another input for color, I am sure that you want to somehow access the value user inputs after all - e.g. in some action. Therefore, you will have to make some bindings that will store that values.
Let's say you need to store them in some kind of an array - e.g. colors. This array will be initially containing only one object, automatically added when user enters the route. This setup (e.g. in setupController hook in route) may look like this:
setupController: function(controller, model) {
controller.set("colors", []);
controller.get("colors").pushObject({ value: "" });
}
And let's handle the click on the button by an action in controller:
actions: {
handleClick: function() {
this.get("colors").pushObject({ value: "" });
}
}
Then, your template can look like this:
{{#each color in colors}}
{{input type="text" value=color.value}}
{{/each}}
Using pushObject method make pushing binding-compliant. Every time you push anything to colors array, the template will automatically rerender and inject another input field with properly binded value to color.value. Thanks to that, in some other action (like submit) you can access all the values provided by the user and process them as you want.

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!

Bind to a value that will be fetched from an API

I have an endpoint that returns a list of artists (json data).
And an endpoint that returns a specific property given an id.
What I would like to do is to iterate through all the artists and display one or more properties in the template to the user but the property should only be fetched from the API if it is bound in the template.
In my ArtistsRoute, I set the model to be all those artists fetched by calling getJSON...
I want, somehow to be able to fetch a property for an artist and display it (through binding).
The Properties map could be stored in the ArtistController maybe.
I could not find a good example for this. Any help is appreciated!
Template example:
Name is on the artist object itself, but the Properties object has been created manually. So in the ArtistController it could be initialized to empty:
Properties = {}
And then it sets Propertes['ShortName'] = to the fetched value.
<ul>
{{#each}}
<li>
{{Name}}
{{Properties.ShortName}}
<img {{bind-attr src=Properties.MainImage}} />
</li>
{{/each}}
</ul>
Should I use a function instead as a property or a Handlebars helper? Like:
{{Property this 'ShortName'}}
where 'this' is the ArtistController and 'ShortName' is the property to fetched. The property id can be calculated through the ArtistController and propertyName.
function(tag, propertyName) {
Ember.$.getJSON('/Properties/' + tag.Id + '_' + propertyName).then(function(response) {
var propertyValueToBind = response.Value; // This is the value I want to display in the template.
});
}
Then the Property function has to know when to rerender the template (once the property has been fetched from the API).
Firstly you'll want to generally avoid properties that are uppercase. They are usually considered global properties, and not in scope.
Ember lazy loads computed properties by default, so adding that functionality to a computed property would be an excellent way to go.
someProperty: function(){
var promise = Ember.$.getJSON('/Properties/buildupurl');
return Ember.ObjectProxy.extend(Ember.PromiseProxyMixin).create({
promise: promise
});
}.property()
Then in your template someProperty would be accessed like this
{{someProperty.value}}
And would be asynchronously populated.
Example: http://emberjs.jsbin.com/OxIDiVU/769/edit

Modifying template based on record saving

I have a form and handle the submit code in my router. My template has this:
{{#if isSaving}}
Saving...
{{else}}
<form>
inputs...
</form>
{{/if}}
My code for saving within the router is this (ctrl is controller):
events: {
saveCompany: function(record, ctrl){
if (!record.get('isDirty')) return;
ctrl.set('isSaving', true);
record.one('didUpdate', this, function() {
ctrl.set('isSaving', false);
});
record.get('transaction').commit();
},
When user clicks submit, "Saving..." is properly shown and hidden when update is done. But I already handle didCreate, DidUpdate etc. in my model definition - by showing some popups, but I still want to be able to prevent the user from fiddling with my form while data is being saved, that's why I use "record.one(...)". What would be best way to do so in a more "generic" way than the way I did it?
If your controller is an Ember.ObjectController you already have access, transparently, to the properties on the content. If the content is the record you're observing, you can just observe isSaving on the controller without any additional code, bindings, or what have you.