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

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>

Related

How to bind a list of checkboxes in AngularJS

I have a list of checkboxes as following :
<div flex="50" ng-repeat="formationType in formationTypeList">
<md-checkbox class="md-warn md-align-top-left"
value="{{formationType.codeFormation}}"
name="formationSelection[]"
ng-checked="formationSelection.indexOf(formationType) > -1"
ng-click="toggleFormationTypeSelection(formationType)">
{{ formationType.nom }}
</md-checkbox>
</div>
This is the format of formationSelection after I send my form :
formationSelection = [
{
codeFormation: 1,
nom: "ENSA"
},
{
codeFormation: 2,
nom: "CPGE"
}
]
In another scenario I want when I open my form to check the checkboxes which are defined in an array as following :
$scope.formationSelection = res.candidatureProjetProfessionnel.formations;
the object res.candidatureProjetProfessionnel.formations contains this :
formationSelection = [
{
codeFormation: 1,
nom: "ENSA"
},
{
codeFormation: 2,
nom: "CPGE"
}
]
And when I inspect $scope.formationSelection it contains the data I got from res.candidatureProjetProfessionnel.formations :
But I don't know why my checkboxes are not checked even though the $scope.formationSelection is not empty.
How can I solve this ?
i'm not sure what the md-checkbox directive is so i'm just going to use a normal checkbox input. Generally speaking, setting a default value for inputs in angular involves 2 things:
Make sure your inputs have ng-model to store the value of the checkbox and for 2 way data binding (so that you can set it from the controller as well)
In your controller set the variable declared in the ng-model to whatever default value you want.
So in you html:
<input type="checkbox" class="md-warn md-align-top-left" ng-
model="formationSelection[$index]" ng-true-value="{{formationType}}"
name="formationSelection[]">
Make sure you use ng-true-value to declare the value of each checkbox when checked. The ng-model is set to formationSelection[$index] which basically means each checkbox is an item inside the formationSelection array, this way the array will be the collection of the values of all checked inputs.
Now $scope.formationSelection = res.candidatureProjetProfessionnel.formations should work
Here's a working plunker:
http://plnkr.co/edit/sGm39DRWH9EOReiiSrIl?p=preview
You have to use ng-model as shown below.It should be an object like $scope.data = {};.This is just an example where hope you can get the point and work on your scenario. Actually you're having individual check boxes as shown below but values are being set through the loop.So you can apply this concept for your use case as well.Hope this will help to you.
Html
<md-checkbox ng-model="data.cb1" aria-label="Checkbox 1">
Checkbox 1: {{ data.cb1 }}
</md-checkbox>
JS
$scope.data = {};
$scope.data.cb1 = true;
Play with it on Codepen
I think that your method isFormation(formationType) on the directive ng-checked it's not return the result.
In your controller create a function
$scope.isFormation(_type){
return $scope.formationSelection.filter(function(f){return f.nom === _type;}).length > 0;
}

Angular 2 Select Component set initial selection

I am trying to create a select component wrapper in Angular 2 using ngModel. The events all fire off correctly once the selection is changed but I cannot set the initial selection when it's rendered.
This is my component:
#Component({
selector: 'my-dropdown',
inputs: ['selectedItem', 'items', 'label'],
outputs: ['selectedItemChange'],
template: `
<div class="field">
<label>{{label}}</label>
<select class="ui search selection dropdown" [ngModel]="selectedItem" (change)="onChange($event.target.value)">
<option value="" selected>Please Select</option>
<option *ngFor="#item of items" [value]="item.value">{{item.label}}</option>
</select>
</div>`
})
export class MyDropdownComponent {
items: DropdownValue[];
selectedItem: DropdownValue;
selectedItemChange: EventEmitter<any> = new EventEmitter();
private onChange(newValue) {
console.log(newValue);
this.selectedItem = this.items.find(item => item.value == newValue);
console.log(this.selectedItem);
this.selectedItemChange.emit(newValue);
}
}
And I'm using it in the view like this:
<my-dropdown [items]="selectItems" [(selectedItem)]="itemToSelect" [label]="'Please Select'"></my-dropdown>
When I set the itemToSelect value in the parent component on init, it does not set the selected option value in the UI.
I have also tried to use the ngModelChange event but it does not fire a change event.
itemToSelect is initially set to an object, so the input property of MyDropdownComponent is initially set to an object. But then in onChange() a string value is emit()ted, which then causes itemToSelect to be set to a string, and hence the input property becomes a string. Not good.
Just consistently use an object and it will work. Also, there is no need to assign this.selectedItem in onChange(), since the selected value will propagate back down from the parent (in general, you should never set input properties in the component – it also looks weird). You can also use ngModelChange now too:
<select class="ui search selection dropdown" [ngModel]="selectedItem.value"
(ngModelChange)="onChange($event)">
private onChange(newValue) {
console.log('nv',newValue);
selectedItem = this.items.find(item => item.value == newValue);
console.log('si',selectedItem);
this.selectedItemChange.emit(selectedItem);
}
}
Plunker
Note that I did not solve the issue of the user selecting "Please select". You'll need to add some logic to onChange() to handle that case.
When I set the itemToSelect value in the parent component on init, it does not set the selected option value in the UI.
Assuming you are using ngOnInit() in the parent, you should set value in one of the lifecycle hooks that are called later (because child doesn't yet exist in ngOnInit()), try ngAfterViewInit()...

How to trigger binding of select based on the changed value in another select?

Let's say that I have list of countries and each country has a list of states/regions. So there are two selects. First to select country, and when country changes I want to trigger binding of the states select. How do you link these two controls to trigger binding of the states select when country changes?
<select id="countries"
data-ng-model="vm.permanentAddress.countryCode"
data-ng-options="country.code for country in vm.form.countries">
</select>
<select data-ng-model="vm.permanentAddress.stateCode"
data-ng-options="state.value for state in vm.getStatesForCountry(vm.permamentAddress.countryCode)">
</select>
UPDATE:
I was probably not explicit in my question as to what I want to do. I do not want to create any new properties that are then watched by angular for a change. I just want to tell anuglar, hey something has changed, go ahead and re-evaluate the binding for this control.
Is it not possible?
In your controller have something like this:
$scope.setStateOptions = function(country){
$scope.stateOptions = /* whatever code you use to get the states */
}
Then your html can be:
<select id="countries"
data-ng-model="vm.permanentAddress.countryCode"
data-ng-options="country.code for country in vm.form.countries"
data-ng-change="setStateOptions(country)">
</select>
<select
data-ng-model="vm.permanentAddress.stateCode"
data-ng-options="state.value for state in stateOptions">
</select>
May be you should use the jquery chanied select plugin:
http://jquery-plugins.net/chained-selects-jquery-plugin
I have used it for 4 select list chained and it worked fine.
Thx
Here is a working example. You just need to use the ng-change to change the model you have set for the states
You can take advantage of the dynamic nature of JavaScript to bind the key from the first list to the second list. Then you only have to set a default value on the change. If you remove the $watch it will still work, the second select will just default to empty when you switch the category.
Here's my data set-up and watch:
app.controller("myController", ['$scope', function($scope) {
$scope.data = ['shapes', 'colors', 'sizes'];
$scope.data.shapes = ['square', 'circle', 'ellipse'];
$scope.data.colors = ['red', 'green', 'blue'];
$scope.data.sizes = ['small', 'medium', 'large'];
$scope.category = 'colors';
$scope.$watch('category', function () {
$scope.item = $scope.data[$scope.category][0];
});
And here's the HTML:
<div ng-app="myApp" ng-controller="myController">
<select id="categories"
data-ng-model="category"
data-ng-options="category for category in data"></select>
<select id="item"
data-ng-model="item"
data-ng-options="item for item in data[category]"></select>
{{category}}: {{item}}</div>
You can, of course, change this to host complex objects and use keys or other identifiers to switch between the lists. The full fiddle is here: http://jsfiddle.net/jeremylikness/8QDNv/

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

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.

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