I recently started experimenting with AngularJS (and Ionic framework), and I just can't seem to get my dropdowns to work with an array of objects.
I can provide more code if needed, but basically I've got the following object in my controller:
$scope.availableCarParks = [{ 'Id': '1', 'Name': 'Parking1' },{ 'Id': '2', 'Name': 'Parking2' }];
And the following html markup:
<select ng-model="selectedCarPark" ng-options="cp.Name for cp in availableCarParks"></select>
For some reason, my dropdown is always empty...
When I do a "console.log(JSON.stringify($scope.availableCarParks))" the moment my controller gets initialized, I see a nice array of my objects like this (in chrome console):
[{"Id":"1","Name":"Parking1"},{"Id":"2","Name":"Parking2"}]
Am I doing anything wrong here? There must be something I'm overlooking...
You can use something like similar to this. Also I have used a default selected value as well.
inside the controller:
$scope.data = {
availableCarParks : [
{id: '1', name: 'Option A'},
{id: '2', name: 'Option B'},
{id: '3', name: 'Option C'}
],
//This sets the default value of the select in the ui
selectedOption: {id: '3', name: 'Option C'}
};
HTML Markup:
<select name="mySelect" id="mySelect"
ng-options="option.name for option in data.availableCarParks track by option.id"
ng-model="data.selectedOption"></select>
Hope this will help you..
Cheers!
Change your ng-option directive input to:
ng-options="co.Id as cp.Name for cp in availableCarParks"
Apparently, what went wrong was that my variable (availablecarparks) didn't have any values in it yet when the view was rendered.
I created a function in my app config and did a route resolve to make sure the api call happened before the controller showed the view, and all is well now.
Related
I am having a problem getting my select to properly set the default option for my data. I am fetching data from a server through an Ajax call. I then want to be able to edit this data using a form. I want to point the select to use options set in a controller object but when you edit the select I want the model to point to the ajax data because that is what I write back to the server. As you can see in my plunkr each of the four items should have their select options filled in but instead all of the selects start empty.
In the official documentation for angular they say to do the following to set the default:
angular.module('defaultValueSelect', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.data = {
availableOptions: [
{id: '1', name: 'Option A'},
{id: '2', name: 'Option B'},
{id: '3', name: 'Option C'}
],
selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
};
}]);
//Then in the HTML file:
<select name="mySelect" id="mySelect"
ng-options="option.name for option in data.availableOptions track by option.id"
ng-model="data.selectedOption"></select>
In my case the options aren't in the ajax data however, only the currently selected option. So I want to manage available options via a controller object but bind the select to the ajax data. Thanks.
https://plnkr.co/edit/Q16QLT?p=preview
You should define which property of "option" you want to bind to:
<select ng-options="option.value as option.text for option in options" ng-model="item.select"></select>
Working demo https://plnkr.co/edit/BezGaYjykfQrFQ9nZop2?p=preview
Change your select to this:
<select ng-options="option.text as option.text for option in options" ng-model="item.select"></select>
This will definately work:
Since your ng-model contains the full option object you need to bind it with the object in ng-options as well
<select name="mySelect" id="mySelect"
ng-options="option as option.name for option in data.availableOptions track by option.id"
ng-model="data.selectedOption"></select>
I am getting the following error: "Expression '{0}' used with directive '{1}' is non-assignable!", as can be shown here: https://docs.angularjs.org/error/$compile/nonassign
Edit: Having moved the config object into the scope this part is resolved, however the models are still not bound as expected. http://plnkr.co/edit/AVs2IW75oWavpsPNDgnb?p=preview
Old plunker: http://plnkr.co/edit/AVs2IW75oWavpsPNDgnb?p=preview
(Try and edit a field and check the console)
I don't really understand the problem which is why that link can't help me to solve it. I am using a directive to bind data, and the data that is being "bound" is actually pointing to a service.
<multi-edit model="profileService.current" config="{
title: 'Edit profile description',
fields: [
{name: 'Title', model: profileService.current.title, input: true},
{name: 'Description', model: profileService.current.description, textarea: true}
]}">
CLick me
</multi-edit>
So I am trying to edit profileService.current.title for example, by using the ng-model config.fields[0].model. It can read the data correctly, but not write to it. What do I need to do in order to be able to write to the correct models?
UPDATED
You should use a scope model for "config".
Put this in your main controller:
$scope.config = {
title: 'Edit profile description',
fields: [{
name: 'Title',
model: 'title',
input: true
}, {
name: 'Description',
model: 'description',
textarea: true
}]
};
and then in your main HTML:
<multi-edit model="profileService.current" config="config">
CLick me
</multi-edit>
Then, in your directive HTML:
<li ng-repeat="(key, value) in config.fields">
<input ng-if="value.input" type="text" ng-model="model[config.fields[key].model]" />
<textarea ng-if="value.textarea" type="text" ng-model="model[config.fields[key].model]"></textarea>
</li>
See the updated plunker.
I am using Angular v1.0.8
I have a select and I am using ng-options directive to populate it with an array of data declared in my Controller.
HTML snippet
<body ng-controller="SelectCtrl">
<select
ng-model="selected"
ng-options="o as o.caption for o in options" />
</body>
Code snippet
angular.module('app', [])
.controller('SelectCtrl', ['$scope', function($scope) {
$scope.options = [
{ key: 1, caption: '1' },
{ key: 2, caption: '2' },
{ key: 3, caption: '3' },
{ key: 4, caption: '4' },
{ key: 5, caption: '5' }
];
}]);
In Chrome, if you select let's say option 3 then, as expected, it gets selected.
In IE10, however, if you select option 3 then option 1 gets selected.
(http://plnkr.co/edit/T9bbEW?p=preview)
This only happens when there is no default selection set in the controller. And subsequent selections done after the "blank" choice is removed gets set correctly.
I suspect that it might possibly be a duplicate of This issue but I am not entirely sure. I am not really dynamically changing the options here although I suppose maybe Angular is since the "blank" choice are getting removed in both browsers.
I do however want this functionality. I don't want to provide a default value for this select because the user needs to make an active choice for me.
Does anyone know a workaround and/or solution for this? Preferably one that does not involve messing with the options using JQuery...
The blank item that angular adds has some odd behavior. The way we've gotten around it is to explicitly add our own blank item and select it via the controller:
angular.module('app', []).controller('SelectCtrl', ['$scope', function($scope) {
$scope.options = [
{ key: 0, caption: ' ' },
{ key: 1, caption: '1' },
{ key: 2, caption: '2' },
{ key: 3, caption: '3' },
{ key: 4, caption: '4' },
{ key: 5, caption: '5' }
];
$scope.selected = $scope.options[0]
}]);
I fix this by adding following default option into select.
<option value="">Pls select</option>
so your select would look like this:
<body ng-controller="SelectCtrl">
<select
ng-model="selected"
ng-options="o as o.caption for o in options">
<option value="">Pls select</option>
</select>
I tested this in IE 11, 10, 9 and it seems to be working.
Please let me know if it works for you as well.
I think this is cleaner than the above solution.
What I am trying to acomplish is to have two different templates within my app: one is generated through ng-repeat like so:
<div ng-repeat="data in tree" ng-include="'templates/question.html'"></div>
And the other is generated like this:
<div ng-include="'templates/question_editor.html'"></div>
So basically the question template will be generated by the user on button click and it can also nest one question within another question using the ng-repeat.
What I am trying to accomplish is that whenever I click on one of those question divs(my question template is basically a divs structure), I want the information(if any) that is inside that div(may be several fields with unique information for each question ), to be populated into some fields in my question_editor template, and as I update the question_editor template fields, it will live update the fields in the question that was clicked.
What I was thinking was in the lines of using one controller and somehow pass the variables from question to question_editor and populate the fields of question_editor. Would it better to use different controllers for each template and then pass the information between the different controllers?
jsFiddle to just show you the structure of my divs: http://jsfiddle.net/cwrEn/1/
can you check this fiddle I edited from yours and let me know if it's what you want!
angular.module("myApp", []).controller("MainController", ['$scope', function($scope) {
$scope.currentQuestion = null;
$scope.questions = [
{
name: 'question 1',
fields:['option 1', 'option 2']
},
{
name: 'question 2',
fields:['option 3', 'option 4', 'option 5']
},
];
$scope.setCurrentquestion = function(question){
$scope.currentQuestion = question;
}
}]);
I have been trying to get my angular ui select2 directive to initialize and have been unable to get it to work with option groups.
The Code:
function testCtrl1($scope)
{
$scope.selectedOptions = ['1'];
$scope.categories = [
{label: 'cat1', options: [{desc: 'one', value: 1}]},
{label: 'cat2', options: [{desc: 'two', value: 2}]}
];
}
The HTML:
<select multiple ui-select2 ng-model="selectedOptions" style="width: 300px">
<optgroup ng-repeat="category in categories" label="{{category.label}}">
<option ng-repeat="option in category.options" value="{{option.value}}">{{option.desc}} - {{option.value}}</option>
</optgroup>
</select>
The Fiddle:
I created the following jsfiddle.
While doing so I notice that it would initialize correctly if I included a second select2 directive that didn't include the option groups (weird). I notice some other odd behavior when including the second select2 but I am not too concerned about it since my goal is just to get testCtrl1 working.
Download latest angular-ui select2 and update line 24:
repeatOption = tElm.find( 'optgroup[ng-repeat], optgroup[data-ng-repeat], option[ng-repeat], option[data-ng-repeat]' );
Now its supports option groups.
Well i've gotten to the same obstacle and want to share my solution. Select2 was not watching the optgroup ng-repeat attribute. You have to add this to your angular ui select2 directive.
Change this:
repeatOption = tElm.find('option[ng-repeat], option[data-ng-repeat]');
To that:
repeatOption = tElm.find('optgroup[ng-repeat], optgroup[data-ng-repeat], option[ng-repeat], option[data-ng-repeat]');
Not sure if this is a clean solution but it works for me.
Github issue
select2 supports <optgroup> through hierarchical data, you can to pass-through a structured object as data instead of using ng-repeat, see
http://ivaynberg.github.io/select2/#data_array
Also search for "Example Hierarchical Data" in the page.
JS:
$scope.model = {
data: [
// both 'id' and 'text' are needed unless you write custom functions
{ text: 'cat1', children: [{id: 1, text: 'one'}] },
{ text: 'cat2', children: [{id: 2, text: 'two'}] }
]
];
HTML:
<input type="hidden" multiple ui-select2="model"
ng-model="selectedOptions" style="width: 300px">
selectedOptions will be an array of objects: [ {id: 1, text: 'one'} ].
For pass-through via the directive, see Angular UI's demo:
http://plnkr.co/edit/gist:4279651?p=preview
EDIT: update code and reference to site