Null model in select in Angular template - angularjs

I have a databound <select> element in an angular app. To bind it I am using:
<select id="AllKeyValuePairsInput" size="4" style="width:500px; height: 175px;" ng-options='item.key as (item.key + ": " + item.value) for item in data.availableOptions' ng-model="selected">
</select>
In my controller I have the following code, that according to the Angular documentation should remove that initial dirty model:
$scope.selected = $scope.data.availableOptions[0];
But I still see an empty entry appearing first in the select. I have it up and running in JSFiddle at https://jsfiddle.net/alchiggs/d12tdapv/
I'd be most grateful if anyone could point me in the right direction. One last point, it's the first bit of Angular I've ever written, so please don't hate me!!!! ;-)

This is how loadInitialData should look, note the change in the default value:
$scope.loadInitialData = function() {
var initialData = [{"key":"Maximum length","value":"200mm"},{"key":"Maximum width","value":"5000mm"}]
angular.forEach(initialData, function(object, index) {
$scope.keyValuePairs.push({ key: object.key, value: object.value});
});
$scope.selected = $scope.keyValuePairs[0].key; // THIS IS THE CHANGE I MADE
}
I've set the default value using the key property and not the element itself because your ngOptions define that the value of each option is item.key

Related

bootstrap selectpicker and cloning

I have been using bootstrap selectpicker where I've added an Add Button for user to replicate the button as much as he wants. Problem is, selectpicker is not working on the second / cloned element and values of dropdown are just showing and not changing on click.
Main Select:
<div id="main_product">
<select name="product[]" class="selectpicker" >
<option value="Tube Lights" >Tube Lights</option>
<option value="Downlights" >Downlights</option>
</select>
</div>
Clone Function:
function clone()
{
var $orginal = $('#main_product');
var $cloned = $orginal.clone();
$cloned.appendTo('#new_products');
// $cloned.find('.bootstrap-select').remove();
// $cloned.find('select').selectpicker();
}
Note that I tried to reassign the selectpicker to the cloned object which is in comments atm, because it dint work also.
Any help would be really appreciated.
I came across this problem but if using the latest version now the select is placed inside the .bootstrap-select element for html5 error handling purposes. The remove() also removes the select, a work around is:
Instead of:
$cloned.find('.bootstrap-select').remove();
Use:
$cloned.find('.bootstrap-select').replaceWith(function() { return $('select', this); });
This will replace the .bootstrap-select element with the select element that it contains inside.
function clone()
{
//you can use :
var $orginal = $('#main_product');
var $cloned = $orginal.clone();
//Or
var $cloned = $('#main_product').clone();
//then use this to solve duplication problem
$cloned.find('.bootstrap-select').replaceWith(function() { return $('select', this); })
$cloned .find('.selectpicker').selectpicker('render');
//Then Append
$cloned.appendTo('#new_products');
}
if we replace the bootstrap-select with the select then the problem is in HTML structure.
so, original element is actual bootstrap-select and cloned are normal select.
take look at following for more clarification.
instead of this
$cloned.find('.bootstrap-select').replaceWith(function() { return $('select', this); });
use
$cloned.selectpicker('refresh');
$cloned.find('.bootstrap-select:odd').remove();
You can please change clone function
function clone() {
var $orginal = $('#main_product');
var $cloned = $orginal.clone();
var $selectPicker = $cloned.find('select');
$cloned
.find('.bootstrap-select').remove().end()
.append($selectPicker).end();
$cloned.find('select').selectpicker();
$cloned.appendTo('#new_products');
}
When using in Form Sets along with other form fields you need to replace and render all the selectpicker mentioned by #cm_mehdi. First find the new form html element and apply the below code:
//Clone new form
let newForm = purchaseForm[0].cloneNode(true);
// Replace and render the cloned html selectpicker
$(newForm).find('.bootstrap-select').replaceWith(function() { return $('select', this); })
$(newForm).find('.selectpicker').selectpicker('render');
// Re-Initialize search in dropdown
$(`#id_form_formfield-${formNum}`).selectpicker({liveSearch: true});

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>

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/

AngularJS ng-repeat default value does not work

I am working with AngularJS and I am so new in that.
My aim is fill a tag SELECT with OPTION element from a datasource.
That is what I do basically:
<script>
function LocalizationController($scope, $http) {
$scope.Regions = [
{ ID: "001", DESC: "DESC_1" },
{ ID: "002", DESC: "DESC_2" },
{ ID: "003", DESC: "DESC_3" },
{ ID: "004", DESC: "DESC_4" },
];
$scope.Region = "003";
$scope.init = function () {
$scope.Region = "003";
}
}
</script>
<div ng-controller="LocalizationController" ng-init="init();">
<input type="button" ng-click="Region='002'" value="test">
<select id="region" name="RegionCode" ng-model="Region">
<option ng-repeat="item in Regions" value="{{item.ID}}">{{item.DESC}}</option>
</select>
</div>
Everything works good, the Select is fill of my items,
but I would like to set default value.
How you can see
- I set my object model which is ng-model="Region"
- I set its default value into init() function by $scope.Region = "003";
when the SELECT is loaded I do not why but dafault value is the first one "001"
I also tried to change value manually by
in that case the SELECT gets the right value selection.
Anyone can explain why it does not work?
I know that is a common problem, I am already looked for that,
any solution suggestion to use NG-OPTION, that directive works good,
it can fill my SELECT with my array of object, it can select default value,
very nice but it does not solve my problem because the value into the
the option element id an integer autoincrement which is not what I want.
so in summary:
NG-REPEAT can render the SELECT how I want but default value does not work
NG-OPTIONS can render the SELECT how I want, default value works but the value into option
item cannot be set how I want.
any suggestions?
thanks in advance
EDIT
I found a "solution"
<div ng-controller="LocalizationController" EXCLUDE-ng-init="init();">
<select id="region" onload="alert();angular.element(this).scope().Region='002'" name="RegionCode" ng-model="Region">
<option ng-repeat="item in Regions" value="{{item.ID}}">{{item.DESC}}</option>
{{init();}}
</select>
</div>
I do not like so much but works pretty good:
- ng-init="init();" does not work good
- If we exclude the initialize of default value into ng-init so EXCLUDE-ng-init="init();" and put the initilize when option are loded it works
Have a look at the code blow, I put {{init();}} after ng-repeat. Everithing works good
{{item.DESC}}
{{init();}}
I do not think is the best solution but Works,
1) I have a droopdown fill of my elements
2) The value of option into my list is CORRECT, "001", "002" and not a stupid autoincremental value which is useless.
I hope that can help someone...
THANKS TO EVERYONE TRIED TO HELP ME
Just use ng-options
<select id="region" name="RegionCode" ng-model="Region" ng-options="option.ID as option.DESC for option in Regions">
And do
$scope.init = function () {
$scope.Region = $scope.Regions[2];
}
When you inspect the select box while using ng-options the values for the options will be like 0,1,2,3.., that is auto increment integer as you said. But don't worry about that. Its the value just for showing up there, but once you post your form you will get the right value as you possess, in your case ID.
use ng-options
and in this case if you play with object (not single values) it should be so
$scope.init = function () {
$scope.Region = $scope.Regions[2];
}

Angular UI Select2, why does ng-model get set as JSON string?

I'm using angular-ui's select2 for a fairly simple dropdown. It's backed by a static array of data sitting on my controller's scope. In my controller I have a function that gets called on ng-change of the dropdown so that I can perform some actions when the value changes.
However, what I'm finding is that the ng-model's property gets set as a JSON string rather than an actual javascript object, which makes it impossible to use dot notation to grab properties off of that model.
Here's the function that handles the value of the dropdown getting changed:
$scope.roleTypeChanged = function() {
//fine:
console.log('selectedType is: ', $scope.adminModel.selectedType);
// this ends up being undefined because $scope.adminModel.selectedType is a
// JSON string, rather than a js object:
console.log('selectedType.typeCode is: ', $scope.adminModel.selectedType.typeCode);
}
Here's a plunker of my full example: http://plnkr.co/edit/G39iZC4f7QH05VctY8zG
I've never seen a property that's bound to ng-model do this before, however I'm also fairly new to Angular so it's likely that I'm just doing something wrong here. I can certainly do something like $.parseJSON() to convert the JSON string back to an object, but I'd rather not unless I have to.
Thanks for any help!
You need to use ng-options on your select if you want to have object values. Actually creating the options yourself using an ng-repeat will only allow you to have string values for the various options:
<select ui-select2
ng-model="adminModel.selectedType"
ng-change="roleTypeChanged()"
data-placeholder="Select Role Type" ng-options="type.displayName for type in adminModel.roleTypes">
<option value=""></option>
</select>
http://plnkr.co/edit/UydBai3Iy9GQg6KphhN5?p=preview
Thanks Karl!
I have struggled a day with this
as a note for others having similar problems as I did,
when using an ng-model not accessible and defined in the controller/directive I solved it like this.
//country.Model has Code and Name nodes
* HTML *
<select
name="country" data-ng-model="country.Model"
data-ui-select2=""
data-ng-change="countryChanged(country.Model)" <!--only for test, log to console-->
data-ng-options="country as CodeAndName(country) for country in countries"
data-placeholder="{{placeholderText(country.Model, '- - Select Country - -')}}" >
<option value=""></option>
</select>
* JS *
function controller($scope, $q, $location, $routeParams) {
$scope.countryChanged = function(item) { // for test
console.log('selectedType is: ', item);
};
//returns the item or the text if no item is selected
$scope.placeholderText = function (item, text){
if (item == undefined)
return text;
return $scope.CodeAndName(item);
};
// returns a string for code and name of the item, used to set the placeholder text
$scope.CodeAndName = function (item) {
if (item == undefined)
return '';
return item.Code + ' - ' + item.Name;
};

Resources