I'm fetching a list of records from App.Resource.find() This is working fine.
For each row of data there is a drop down box with fixed values. When a change is made to a drop down box I'd like to issue a POST or PUT request back to the server to update that row with the newly selected value from the drop down.
I am having trouble with two things:
How can I get the ID and selected value of the dropdown in my model or controller
How can I take those values and issue a request to the server. Is there App.Resource.update...?
I have a jsBin of the working example with local data: http://jsbin.com/OcAyoYo/84/edit
Ok, here's one approach to get the selected value, let's put things where they should go, ok, first of all, let's create a controller which is going to decorate your Response records, you mixed names, you're using Post, so, I'll use that name, here is the controller:
App.PostController = Ember.ObjectController.extend({
selectedChanged: function() {
//here, you have access to the selected value with this:
// this.get('selected')
//And also, this controller represents you object rendered on the screen,
//so, you can change it here if you want like this:
//this.set('whataverPropertyYouWantToChange', 'newValue');
//then you can save this record(send the request to the server) by just doing this:
//this.save(); this will make a request to the server
}.observes('selected')
});
then, in order to use that controller, change the loop where you render the records, to this:
{{#each model itemController="post"}}
<tr>
<td>{{author}}</td>
<td>{{book}}</td>
<td>
{{view Ember.Select
contentBinding= 'App.names.content'
selectionBinding='selected'}}
</td>
</tr>
{{/each}}
just be careful, in PostController, the observer will be fired even if the 'selected' property has null values, you need to verify if it is not null.
Related
I currently list a set of options for ng-options from a resource that contains JSON.
[
{
id:23,
name:"Other"
},
{
id:24,
name:"Crew"
},
{
id:25,
name:"Announcer"
},
{
id:26,
name:"Producer"
},
{
id:27,
name:"Cameraman"
},
{
id:28,
name:"Monitor"
}
]
This is all added into my scope at $scope.broadcaster = response.data. I then loop through everything in my options by a simple ng-options.
<select ng-model="selectedrole" ng-options="roles as roles.name for roles in broadcaster" ng-init="selectedrole=broadcaster[0]">
</select>
Everything goes good once the page loads up. I can select from my list of names and the ng-init starts on the first selection as anticipated. However I have a few issues that I can't seem to resolve.
1) In my doc I set up {{selectedrole}} and I expected to see the contents of my model on the page reflected by my current selection. Instead I see no output at all. I can't tell if the model is even being updated properly so I'm not sure if I can use it in my formdata.
2) This select is generated on click so users can select a role for more than one person. However since the model is the same, any selection is copied over which ever one is changed. I need to find a way to output the model to check the data, but make that model dynamic so i can get a list of results from all the different selections.
EDIT:
Now this is really crazy. I mocked it up in a plunker and its at least showing the model just fine. Are there some conflictions I should worry about that would stop the model from updating? I literally copy pasted my data and its working in plunker but not my project.
http://plnkr.co/edit/GbdOmdjj1M3OuZKO5cSq?p=preview
EDIT2:
Even more info. As I stated before, the select is created when a user clicks on a function that creates an ng-repeat with user information and a new select option for role. If I place the {{selectedrole}} within that ng-repeat I actually get all the data returned when I user selects it. It seems that since the click creates a push of new data, it will not work outside each item. The issues now is that every instance has its own model so i need to figure out how to gather all this data from each ng-repeat and post it to the form. I'll try to update as I work through the issue.
Summary
What's a clean way of updating a select element in a child controller scope so that the selected item's ID matches an ID in a parent scope?
Details
I have two controllers:
OrderController
CustomerController
OrderController loads an Order and shows it on an order form.
CustomerController is the scope for a subform within the OrderController form. It shows a list of all customers, with the default customer being the one associated with the order. The user can edit the details of the selected customer or add a customer right from the subform.
Possible Solutions
I've thought of two so far, but neither seems very good.
Include a list of all customers in the JSON passed to the Order $resource. That won't work because the user needs a full separate controller to update customers on the subform.
Fire an event when the customers have loaded within CustomerController. OrderController handles that event, updating the select based on its order's customer_id property. That seems better but still hacky.
To communicate between two controllers you would usually broadcast/emit, e.g:
(Coffeescript)
CustomerController:
Api.Customer.get(
id: $scope.customer_id
).$promise.then (data) ->
$scope.$emit 'event:updateOptionId', id
OrderController:
$scope.$on 'event:updateOptionId', (event, id) ->
$scope.customer_id = id
I don't know the structure of your app but this is passing the new customer id to order controller based on an action in the customer controller. If you post some of your code you may get a more thorough answer.
I found that Angular does handle the update automatically. The problem was that my server was returning a one-item array for the order data. So the customer_id of the order property wasn't going into $scope.order.customer_id; it was going into $scope.order[0].customer_id. Correcting that on the back end solved the issue.
I'm looking for a way to update a select element's optionsText after I've received my data from an ajax call.
I've got what I think is a fairly standard view setup of a select element with multiple associated fields and check-boxes.
Before I do an ajax call to get the data I use the optionsText property to set a "Loading data..." option and once the data call is done I want to delete the optionsText and set the select option to the first "real" one in the list, aka the first element in the array returned from my data call.
If not delete the optionsText, I want to at least change it to "Pick a foobar" so the user knows the data call is done.
Anyone have any ideas? Thanks!
You just have to change the values of the options model as done here
var vm=function(){
var self=this;
self.selected=ko.observable();
self.options=ko.observable([{txt:'Loading',val:-1}]);
self.status=ko.observable('Loading');
self.init=function(){
setTimeout(function(){
self.status('Loaded');
self.options([
{txt:'First Option',val:0},{txt:'2nd Option',val:1}]);
},1000);
}
self.init();
}
ko.applyBindings(new vm());
http://jsfiddle.net/dhanasekaran/SRLvj/
I have a dijit Select widget and need to do something when the user clicks one of the dropdown items. Meaning I need access to the clicked item, to retrive some information, and call one of my own functions.
I've tested to attach an onChange on the select and I can get the text value selected fine. But I need the object and not the value. The object holds more values in a data-info-attribute.
Basically what I'm trying to achieve is to show one value in the list but send along more values to populate other fields when selected.
Background: This is a typeahead field populated thru AJAX by a server function. There IS a store attached but it's empty (as far as I can tell) so I've been unsuccessful trying with: .store.fetchItemByIdentity - always returns nothing.
ta.store.fetchItemByIdentity({
identity: ta.getValue(),
onItem: function(item, request){
console.log(item),
console.log(request)
}
})
I expect the log to show item- and request-object, but they're both undefined.
ta.getValue() get's the selected value as expected.
What's the best way to achieve this?
Have a look at my answer to onChange not sufficient to trigger query from Dojo Combobox and also to jsFiddle mentioned there. I added code specific for your needs there:
select.dropDown.on("itemClick", function(dijit, event) {
var node = dijit.domNode;
console.log(domAttr.get(node, "data-info-attribute"));
// or
console.log(node.dataset.infoAttribute);
});
I have a list of images each with a 'Like' button. When the 'Like' button is clicked, an AJAX request (containing the item_id and user_id) will be sent to the serverside to record the Like (by adding a new row in the table likes with values for item_id and user_id).
The model Photo is used for the images displayed on the page. If I understand correctly, this.model.save() is used if I want to update/add a new Photo, so it is not suitable for recording 'Likes'. Therefore, I have to use something like $.get() or $.post(). Is this the conventional way?
Or do I create a new model called Like as shown below, which seems to make it messier to have a View and template just for a Like button.
Like = Backbone.Model.extend({
url: 'likes'
});
LikeView = Backbone.View.extend({
template: _.template( $('#tpl-like').html() ),
events: {
'click .btn_like': 'like'
},
like: function() {
this.model.save({
user_id: 1234,
post_id: 10000
})
}
});
In similar cases to this I've used the $.get method rather than create a new model, obviously this will depend on your application, but here are my reasons.
This case appears to have the following characteristics:
Like is a relationship between a person and a photo,
you seem to have a server side resource that accepts the photo and user ids to create this relationship already,
you probably have no other information attached to that relationship, and
you probably don't have significant view logic to go with the like itself
This is better handled by adding another attribute to your Photo object, that contains the number of likes. Then use $.get to create the like, and a 200 response will simply update the photo object to up it's count (and hence the view). Then the server side just needs to include the like count as part of it when it returns.
I'm assuming here that once a like is made you won't be updating it. If you do need to update or delete it, I might still keep using the $.get. You can add a likes array to your photo object where each element is the id of the like resource. The view will display the length of the array as the count, and if you need to delete the like, you have access to the id and you can use $.post. Just make sure you don't use .push to add values to your array since that'll bypass backbone's set method and you won't get your event callbacks. You need to clone the array, then push, and then set it when you make changes.