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.
Related
This should be simple to do. I just can't pass the value of the input to the product-details view. I'm trying to create a unique template page for each item added to the list. Clicking the 'details' link should take the user to the unique page. I understand how dynamic segments works, I'm just getting stuck somewhere.
Thanks!
http://emberjs.jsbin.com/midivu/1/edit?html,js,output
In your link to helper you need to pass the parameter in...
{{#link-to 'details' name class="add-item-button"}}
Example..
If you imagine link-to as a function then in your case it would be
linkTo(route, segment, etc...)
But imagine it this way just to understand the adding parameter...
To fix your Details Route
App.DetailsRoute = Ember.Route.extend({
model: function(params) {
return userList.findBy('name', params.itemName); // assuming you want to find the details by it's name
}
});
This is because you did not create a data store. You are using a global variable as your data store, therefore, you must get it from the global.
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.
I need some ideas on how to create a search filter in EmberJS where the search results can persist across views. Lets say I have a list of contacts and I filtered the list. Assume this route is called Contacts/Index
Now I have a second route called Contacts/Details. The user will be directed to this route once they select a result from the contact list. Now when they click 'Back To Contacts', I want the previous filter to be still applied instead of showing all the Contacts.
I didn't write any code yet, so I can't provide a JSFiddle. All I can think of now is probably to create a global variable to keep track of the text that is used to filter and apply that when transitioning back to the Contacts/Index view but I'm not sure if it is the right way to do it.
This is just pseudo-code that doesn't really care what your filter type is, but you could apply a filter property to the ContactsIndexController:
App.ContactsIndexController = Ember.ArrayController.extend({
//...
filter: 'name=bro',
filteredContent: function () {
if(this.get('filter')){
return this.get('content').filter//...;
} else {
return this.get('content');
}
}.property('filter')
//...//
});
Whenever you change the filter, make sure to update the filter property:
this.set('filter', 'foo=bar');
Then in your handlebars template you always loop over filteredContent:
{{#each filteredContent}}
{{/each}}
When you transition back and forth between the Contacts inner routes, it should retain the filter when you return to the index.
You can also see how this pattern could be used to take this one step further and manipulate the filter from literally anywhere in the application. If you aren't in that controller's context, you can still update that property and bindings will appropriately render the computed property next time you visit.
From another controller:
this.set('controllers.contacts-index.filter', 'year=20x6')
From a route:
this.controllerFor('contacts-index').set('filter', 'year=20x6')
From a view within the index controller:
this.set('controller.filter', 'year=20x6')
I'm sure you get the idea.
This is, of course, one of several approaches you could take. I prefer this particular pattern.
Hope that helps and good luck!
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.
I have an application in ASP.MVC. The requirement is that I select a person from a list of people and click 'Info' and it should load the details of the person in that page. I have the Info controller and everything works fine if I go to the Info page from a different controller. In the page I am trying to make it work with JavaScript and it doesn't seem to take me to the desired page but to a different controller.
I have a ToDoList controller and in the .cshtml I have this code on click of the Info link.
function DoInfo#(i.ToString())() {
$("#sessionid").val("#Model.cSessionId[i]");
alert("hey");
$("#PageController").val(66);
$("#formID").submit();
}
I go to the ToDoList controller to do the redirection like this
if (viewModel.PageController == 66)
{
pass = new PassingData();
pass.personid = TSSessionService.ReadPersonId(viewModel.SessionId);
TempData["pass"] = pass;
return RedirectToAction("Index", "Info");
}
It never goes there and instead goes to a different controller. I cannot seem to find how they are linked and why is it not going back to controller where the Info link button is i.e. back to the ToDoList controller.
Let me know if it is not clear and I will try to explain again and I will give any other details.
I guess I'm confused as to why you are doing this as a combination of form and JavaScript. Are there other properties that you need to pass along that you are not posting above? Why do you need to use JavaScript to do this if you are just returning a new view?
You indicate in your post that when a person is selected from a list you need to go to a controller and display a view. This seems fairly straightforward, and I would like to suggest simplifying the problem.
Start with this: change your link to not use a form or JavaScript. Just make it a link. If it is text, you can use #Html.ActionLink() and even pass in the parameters you need.
If you're not displaying text, just use #Url.ActionLink() in your href property of the anchor you're wrapping your element with. Both of these allow you to leverage routing to ensure the correct path is being constructed.
If the controller that you are trying to get to has access to whatever TSSessionService is, then you don't need to pass through the TempData["pass"] you are trying to push through, so it makes it cleaner in that way as well.
If you do need to submit a more complicated value set, I would recommend coming up with a generic .click() event handler in jQuery that can respond to any of the clicks, bound by a common class name. You can use a data-val attribute in your link and read from $(this).attr('data-val') in your handler to store/fetch other important info. This allows you to more easily build up an object to POST to a controller.
Hope this helps some, but if I'm missing a critical point then please update the question above.