how to set the default 'select' ng-model to an object? - angularjs

I am trying to do a search engine interface with angular. The user selects some parameters in a form, click "search" and then it fills the url with the parameters using $location.search()
the search interface parameters which are used to build the form :
params = {
milestones: [ "a", "b", "c", "d", etc. ],
properties: [
{ "name": "name A", type: "text" },
{ "name": "name B", type: "checkbox" },
{ etc. }
]
}
inside the controller :
$scope.query = $location.search(); // get the parameters from the url
$scope.search = function (query) { // set the parameters to the url
$location.search(query);
};
and the html of the form
<select ng-model="query.milestone_name" ng-options="ms for ms in params.milestones">
<option value="">-select milestone-</option>
</select>
<select ng-model="property" ng-options="prop.name for prop in params.properties" ng-change="query.property_name=property.name">
<!-- if the object 'property' was passed in the url, it would look like this `%5Bobject%20Object%5D`, so its 'name' parameter is converted to a string -->
<option value="">-select property-</option>
</select>
<span ng-switch="property.type">
<label ng-switch-when="text">{{query.property_name}}: <input type="text" ng-model="query.property_value"></label>
<label ng-switch-when="checkbox">{{query.property_name}}: <input type="checkbox" ng-model="query.property_value"></label>
</span>
<button ng-click="search(query)">search</button>
and somewhere else in the page is the list of results.
the user can also access to a search result page with an url like this:
http://myapp.com/search?milestone_name=a&property_name=name%20A
almost everything works fine : the list of results is displayed, the "milestone" parameter is pre-selected with the correct value in the select component, but not the "property" parameter because it's not a string, it's an object.
how can i set the default value (ng-model) of the select component to an object ?
or any other idea on how i should do this ?

When using an array of objects for the select to iterate over, the ng-options directive needs to have an attribute of the object to match against (and differentiate between arrays)
Use the track by section of the directive declaration eg
<select ng-model="property" ng-options="prop.name for prop in params.properties track by prop.name" ng-change="query.property_name=property.name">
<!-- if the object 'property' was passed in the url, it would look like this `%5Bobject%20Object%5D`, so its 'name' parameter is converted to a string -->
<option value="">-select property-</option>
</select>

You can use this form of comprehension expression in ngOptions: label group by group for value in array. Html drop down list will display only name of selected object. Model will contain whole selected object. You can set selected object from controller.
<select ng-model="property"
ng-options="prop as prop.name for prop in params.properties">
</select>
Check this plnkr example.

ng-options is generating some options to be used with ng-model. In your syntax (prop.name for prop in params.properties) you've told it to bind to the object found in the array (as oppose to a property on it - which is what you want to do) and use its name property as the value to display. So when you try and set the ng-model to be an object that's not in the ng-options array nothing happens - I'm guessing because it's using reference/shallow equality and not deep equality. So what you should do is either:
Convert the ng-options object to be an array of strings.
Use a syntax that involves keys, such as:
prop.name as prop.name for prop in params.properties
http://jsfiddle.net/C5ENK/
If that doesn't suit your needs let me know why and I'll see if I can help further.

i found a kind of solution…
when selecting a property, it saves the index of this object and then when the page loads, it sets the ng-model of the select to the value of this index. it uses this : example for setting the index and this example for getting the value of this index in the array of objects.

Related

Using ui-typeahead to populate model with object but show string of that model

Hello everyone I have the following code using ui-angular typeahead
<input type="text" ng-model="itemSelected"
uib-typeahead="item.name for item in getItems()" id="itemInput" class="form-control">
the data that getItems() returns is of this structure:
[{itemId : 12345, name : "name of item"} ....]
Now what I would like to happen is the type ahead to give it's suggestions by showing item.name (which it currently does!) however what it does is sets itemSelected to the string not the object.
if I change the html such that the list comprehension reads item for item in getItems() I get the typeahead giving me the object (not what I want) although it does set the itemSelected variable to the object of my selected typeahead.
I would like the typeahead to display item.name but I would like the object item to be put into itemSelected. How can I achieve that?
You can try the following...it works fine
https://plnkr.co/edit/Zsgw5RKAEi5C2IKLcpGR?p=preview
<div>seleted state: {{state4}}</div>
<input type="text" ng-change="onedit()" ng-model="state4" uib-typeahead="state as state.name for state in states | filter:$viewValue | limitTo:8">

Angular: Select dropdown with ng-model-options setter getter set to true

Can somebody show me an example on how to bind ng-options to a getter and setter model, a plnker demo will be great.
Example on what i want to accomplish:
// As you can see the item is a object with two properties example:
// {Text: "hello", Value: 10}
setgetObject: function(value) {
if (angular.isDefined(value)) {
myObject = angular.copy(value); //copy the incoming object
}
return ????
}
<select class="form-control" name="rumFra" ng-model="getterSetter.setgetObject"
ng-options="item as item.Text for item in vm.configuration.Form.Room track by item.Value"
ng-model-options=" {getterSetter: true }">
Each time I make a new selection on my dropdown it will set the myObject with the new value but the dropdown is not effected even if I return the input element.
A working example on how to use Select tag with ng-options and ng-model-options="{setterGetter= "true"}" will be appreciated :-)
Look at Numyx's example:
http://plnkr.co/edit/SqJG8NP7e9NB9okcD4hN?p=preview
Because it is working but not with objects. Can somebody do it with objects?
Just use ng-model . ng-model binds the input,select and textareas.
see the example
<select ng-options="p.name for p in animal"
ng-model="selectedanimal"></select>

Update ngmodel from Select

We're attempting to display a customer's information based upon the contact they select. When we use ng-options it works as expected. We are, however, using Ui.Select2 and "ui-select2 is incompatible with ." So we are forced to use ng-repeat and it isn't working as expected.
JS:
var app = angular.module('App', []);
app.controller('Ctrl', function($scope){
$scope.contacts =
[ {
'CntctKey': '331518',
'Name': 'Cheryl',
'Phone': '55555115',
'PrimaryCntct': '0'
} ,
{
'CntctKey': '118431',
'EmailAddr': 'pizzamaybe#gmail.com',
'Name': "Stephanie Pizza",
'Phone': '555552255',
'PrimaryCntct': '1'
} ];
});
HTML
<h3>With ng-options</h3>
<select ng-model="contactedPerson" ng-options="contact.Name for contact in contacts"></select>
<input ng-model="contactedPerson.Phone"/>
<input ng-model="contactedPerson.CntctKey"/>
<br>
<h3>With ng-repeat</h3>
<select ng-model="contactPerson1" >
<option ng-repeat="contact in contacts" value="{{contact}}">{{contact.Name}}</option>
</select>
<input ng-model="contactPerson1"/>
<input ng-model="contactPerson1.Cntctkey"/>
http://plnkr.co/edit/9D9LTCnBOGAo2ftA1jbU
You can see that with ng-repeat it shows the object but we can't drill it into it any further.
Is there a good way to do this besides using ng-options? Thanks in advance!
The problem is that you are using value="{{contact}}"
This causes angular to print the object as a JSON string.
So when the value gets assigned from the ng-model in the select list, the variable is assigned a string value i.e.
"{"CntctKey":"331518","Name":"Cheryl","Phone":"55555115","PrimaryCntct":"0"}", rather than the object's itself.
This is why in your plnkr, your second field which has ng-model="contactPerson1.CntctKey" has no value, because for a string, this property is undefined.
to fix this you can just use the index of the array element to reference the object.
You can access this index by using ng-repeat's key mapping (contactKey, contact) in contacts.
Or if you are just storing everything in a flat, contiguous array (like in the example), just use ng-repeat's $index variable.
i.e.
<select ng-model="contactPerson1Index" >
<option ng-repeat="contact in contacts" value="{{$index}}">{{contact.Name}}</option>
</select>
<input ng-model="contacts[contactPerson1Index].Phone"/>
<input ng-model="contacts[contactPerson1Index].CntctKey"/>
See updated plnkr: http://plnkr.co/edit/4thQmsZamN3tt0xpscj9
for more info on key mapping and ng-repeats internal variables, see: https://docs.angularjs.org/api/ng/directive/ngRepeat

angularjs : select with different (key, value) not working properly

I am trying to load angular "select" with the following code
<select class="span11" ng-model="user.countryOfResidence" ng-options="c.option as c.value for c in countries" required>
Its loads the data into the select but the default selected value is empty.
my countries array is
$scope.countries = [{option:'TL', value:'TIMOR-LESTE'},
{option:'TK', value:'TOKELAU'},
{option:'TJ', value:'TAJIKISTAN'},
{option:'TH', value:'THAILAND'},
{option:'TG', value:'TOGO'},];
if i change 'TL' to 'TIMOR-LESTE', (same string for "option" and "value") it works fine. Can any one kindly tell me what is the problem with my code.
user object is
$scope.user = {
countryOfResidence : $scope.countries[0].value
};
A select populated with ng-options will set the ng-model field to what is specified as the value, not the option
In the example you've given, you're setting user.countryOfResidence to countries[0].value, which in this case is 'TIMOR-LESTE', but the value key is 'TL', so it won't select it by default.
For better readability, I always like to structure my select options with 'label' and 'value' keys, like so:
// Controller
$scope.countries = [
{value:'TL', label:'TIMOR-LESTE'},
{value:'TK', label:'TOKELAU'},
{value:'TJ', label:'TAJIKISTAN'},
{value:'TH', label:'THAILAND'},
{value:'TG', label:'TOGO'}
];
$scope.user = {
countryOfResidence: $scope.countries[0].value
};
};
// View
<select class="span11" ng-model="user.countryOfResidence" ng-options="c.value as c.label for c in countries" required=""></select>

select2 widget fails to update the selected value programatically

Working with angular, select2 widget.
I am declaring it in HTML something like this:
<div>
<select id = "dropdown"
...
<option value = "1" id="1">1</option>
<option value = "2" id="2" >2</option>
<option value = "3" id="3"" >3</option>
/select>
</div
and want to programatically change the selected item (called from another function).
When invoking the code:
$("#dropdown").select2().select2('val', "3")
I can see that the value at the dropdown changes, but when actually accessing the model attribute of the drop down (to fetch the selected item), it is not set to what I tried to set it to.
When checking the onChange event of the dropdown, I can see the e.val is undefined.
See the next fiddle as an example (after click the link, I wasn't suppose to get "undefined" in the alert box): http://jsfiddle.net/kcArV/1/
Any ideas what I am doing wrong ?
It should be
$('#attribute').select2().on('change', function(e) {
alert($(this).val());
});
e is the event object, not the select control, the method context this points to the select element, so you can call the .val() to get the selected value
Demo: Fiddle

Resources