I have a select set with States from JSON data:
<select name="ParentState" ng-model="selectedState" ng-options="s.StateID as s.StateCode for s in cStates | orderBy:'StateCode'">
<option value="">Select State...</option>
</select>
and would like to set the selected state as the state returned for the logged in user but I'm entirely sure how to accomplish this in Angular. Here's what I've tried and it isn't working.
angular.forEach($scope.cState, function (s) {
if (s.StateCode == xParentState) {
$scope.selectedState = s.StateCode;
}
});
xParent is this state initials e.g. 'MI' for Michigan
The ngModel is set to the StateID (as seen in your ngOptions - value as text for object in array) - so set that rather than StateCode
if (s.StateCode == xParentState) {
$scope.selectedState = s.StateID;
}
Check the documentation for `ngOptions.
You're using the select as label for value in array expression here. So to set the ngModel, you will need to set the StateID.
Assuming you have an object like:
xParentState: {
StateID: 1,
StateCode: 'MI',
StateName: 'Michigan'
}
Instead of iterating over the array of states, you can then set the value directly with $scope.selectedState = xParentState.StateID or you could use ngInit for setting it in the template (e.g. when the user reloads the page):
<select ng-model="selectedState" ng-options="s.StateID as s.StateCode for s in cStates | orderBy:'StateCode'" ng-init="selectedState = xParentState.StateID">
<option value="">Select State...</option>
</select>
Related
I'm working on a project, and I need to bind the options value to object key's in such a manner that, on selecting an option, it gives 1, else other variables remain 0.
My HTML Code:-
<select required class="custom-select">
<option disabled>Select an option</option>
<option ng-model="PredictCtrl.detail.building_type_AP">Apartment</option>
<option ng-model="PredictCtrl.detail.building_type_GC">Independent House / Villa</option>
<option ng-model="PredictCtrl.detail.building_type_IF">Independent Floor / Builder's Floor</option>
<option ng-model="PredictCtrl.detail.building_type_IH">Gated Community Villa</option>
</select>
Variable to bind -
PredictCtrl.detail = {
building_type_AP: 0,
building_type_GC: 0,
building_type_IF: 0,
building_type_IH: 0
}
Generally, binding is done with select tag, which gives the value of the selected option, but I want in such a way that, when I click on Apartment option, it's bind variable PredictCtrl.detail.building_type_AP becomes 1, rest remains 0. Similarly, it does with other options.
I want to send the data as the same format through API.
So, please Help me out.
Sorry If I was not very clear with explaining or for any typo.
Thank you in advance.
You should take a look at the NgOptions directive which is the "angularjs" way of working with the select-tag.
It sould be able to fulfill your requirement as you will get the selected option in the SelectedOption object.
Here's an example
angular.module("app",[]).controller("myCtrl",function($scope){
$scope.details =
[
{name:"Apartment", value:1},
{name:"Independent House / Villa", value:2},
{name:"Independent Floor / Builder's Floor", value:3},
{name:"Gated Community Villa", value:4}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<select required class="custom-select" ng-options="item as item.name for item in details" ng-model="selectedOption">
</select>
<p>SelectedOption: {{selectedOption}}</p>
</div>
None of the answers at my time of writing actually present a functioning solution, so here's one.
Don't scatter ng-model directives across different option elements, it's unnecessary.
You can achieve what you want by using ng-options to enumerate all your choices, a single ng-model to keep track of the selected option, and ng-change to apply the values as you described (i.e. 1 on the selected key, 0 for everything else).
I've assumed you've got a requirement to keep the structure of detail as is. If it can be changed, then I'd recommend associating each labels with each it's respective building_type_ to keep things together.
See below.
angular
.module('app', [])
.controller('PredictCtrl', function () {
this.selectedDetail = null;
this.detail = {
building_type_AP: 0,
building_type_GC: 0,
building_type_IF: 0,
building_type_IH: 0,
};
this.labels = {
building_type_AP: 'Apartment',
building_type_GC: 'Independent House / Villa',
building_type_IF: 'Independent Floor / Builder\'s Floor',
building_type_IH: 'Gated Community Villa',
};
this.changeDetail = function () {
for (var key in this.detail) {
this.detail[key] = +(this.selectedDetail === key);
}
};
});
<script src="https://unpkg.com/angular#1.7.4/angular.min.js"></script>
<div ng-app="app" ng-controller="PredictCtrl as PredictCtrl">
<select
ng-model="PredictCtrl.selectedDetail"
ng-options="key as PredictCtrl.labels[key] for (key, value) in PredictCtrl.detail"
ng-change="PredictCtrl.changeDetail()"></select>
<pre>{{ PredictCtrl.detail | json }}</pre>
</div>
try like this:
in your controller:
$scope.details = [
{
name: "building_type_AP",
value: "Apartment",
state: false
},{
name: "building_type_GC",
value: "Independent House / Villa",
state: false
}/*add more here*/
];
$scope.setActive = function(detail){
detail.state = !detail.state;
}
in html template:
<select required class="custom-select">
<option disabled>Select an option</option>
<option ng-repeat="detail in details" ng-click="setActive(detail)">{{detail.value}}</option>
</select>
in the end just go through $scope.details and parse false to 0 and true to 1 OR just do this inside setActive function
I have an existing select tag with existing option tags, one marked "selected", for example:
<div class="form-group">
<label class="control-label">Test</label>
<select ng-model="vm.testNumber">
<option>Choose...</option>
<option value="1">one</option>
<option value="2">two</option>
<option value="3" selected>three</option>
</select>
<p class="help-block">{{vm.testNumber}}</p>
</div>
Angular is binding to the model correctly and spits out "3" in the help block when the page loads, but option 3 is not selected. It binds and shows 3 as selected if I use text for the value attributes on each option, but not when it's a numerical value. Instead it inserts an option at the top of the select list:
<option value="? number:3 ?"></option>
What am I doing wrong?
From Angular DOC
Note that the value of a select directive used without ngOptions is always a string. When the model needs to be bound to a non-string value, you must either explicitly convert it or use ngOptions to specify the set of options. This is because an option element can only be bound to string values at present.
If you change your code as like as below code snippet, you don't need to do any explicit string conversions.
<select ng-model="vm.testNumber" ng-options="item.value as item.label for item in [{label: 'one', value: 1}, {label: 'two', value: 2}]">
<option value="">Choose...</option>
</select>
Turns out you need to add a directive to make this work correctly. #codeninja.sj's answer ends up replacing 'one' with 1, 'two' with 2, etc. In the documention, the last example has this directive, convert-to-number
angular.module('app').directive('convertToNumber', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
ngModel.$parsers.push(function (val) {
return parseInt(val, 10);
});
ngModel.$formatters.push(function (val) {
return '' + val;
});
}
};
});
None of the other examples in the documentation worked for me.
Update #codeninja.sj's updated answer does work, however, figure this directive will cut down on magic strings in my code.
I have three select menu that bind to each other and want to set selected value of two select menus. Value that I want to set comes with scope. I try ng-init but that didn't work. Working Plunker
<select ng-init="selManga=direk" ng-model="selManga" ng-options="manga.seri for manga in mangas">
<option value="">Select a Manga</option>
</select>
<select ng-init="selChapter=bacanak" ng-show="selManga" class="browser-default" ng-model="selChapter" ng-options="+idx as chapter.klasor for (idx, chapter) in selManga.randomword">
<option value="">Chapter</option>
</select>
<select ng-show="selManga.randomword[selChapter].yol" class="browser-default" ng-model="selPage" ng-options="+idx as (+idx + 1) for (idx, page) in selManga.randomword[selChapter].yol">
<option value="">Page</option>
</select>
Javascript:
.controller('nbgCtrl',function ($scope, MMG, $stateParams) {
$scope.direk = $stateParams.seri;
$scope.bacanak = $stateParams.klasor;
MMG.adlar.success(function(loHemen) {
$scope.mangas = loHemen;
});
$scope.next = function (manga, chapter, page) {
var nextPage = page + 1;
if (angular.isDefined(manga.randomword[chapter].yol[nextPage])) {
$scope.selPage = nextPage;
} else if (angular.isDefined(manga.randomword[chapter + 1])) {
$scope.selChapter = chapter + 1;
$scope.selPage = 0;
}
}
})
To extract the values for the manga,chapter and page from the url you should use the $routeParams object, which your module should include ngRoute.
I've prepared an example here it might not be obvious but if you download the code and run it in your own browser you can access routes like Manga/Naruto/ch/100 from the url bar.
Once you've restructured your application to use routes and routeParams, in my example I directly bind the chapter and page I get from the url to the view but if you bind them to the models of your dropdowns the dropdowns will update.
$scope.params = $routeParams;
$scope.selManga = $scope.params.bookId
This does not update the url as you select from the dropdown.
In your code you have assign direk and bacanak value more than one times which can cause issue. Set variable property only once.
$scope.direk = $stateParams.seri;
$scope.bacanak = $stateParams.klasor;
$scope.direk = $stateParams.xy; //Remove if not required
$scope.bacanak = $stateParams.xz; //Remove if not required
Set selManga value from $stateParams instead of setting it to direk
$scope.selManga = $stateParams.seri; // Set selManga from $stateParams
$scope.selChapter = $stateParams.klasor; // Set selChapter from $stateParams
The reason why ng-init="selManga=direk" not work is because Syntax error: ng-init="selManga=direk" should be ng-init="selManga='direk'" but after making syntax correct, dropdown will not set because of ng-repeat. ng-init set value to model but at time of setting value ng-repeat doesn't complete setting value for options so selManga set from ng-init not update option to dropdown.
I have this code and information:
$scope.options = [
{ id: 1, label: "My label" },
{ id: 2, label: "My label 2" }
];
$scope.selected = 2;
<select ng-options="opt.label for opt in options" ng-model="selected">
<option value="">Select one</option>
</select>
However, the options are created like this:
<select ng-options="opt.label for opt in options" ng-model="selected">
<option value="">Select one</option>
<option value="0">My label</option>
<option value="1">My label 2</option>
</select>
How can I set the selected option to My label 2? I know it can be done:
$scope.selected = $scope.options[1];
But my problem is that option is created in a directive, and at that moment I don't know 1) how many values has $scope.options, nor 2) what is the index of the selected option in database. The only thing I know is the id (which is in the object).
The html of my directive is something like this:
<select ng-switch-when="select" ng-model="form.model[element.model]" ng-options="{{element.rule}}"></select>
Where element.rule is:
rule: "role.role for role in element.options"
And element.options has the array with options, and form.model[element.model] has the id of the option selected.
How can I get the index of the element with ID X in the array $scope.options? I'm very sure that will give me the solution, but I don't know how to do it...
Just set the correct model value when initiating the controller. You can easily get the correct array value if you know the ID by using a filter:
$scope.selected = $filter('filter')($scope.options, {id: 2})[0];
The issue with your code as I see it is that the 'selected' value coming out of your database is the ID of the object selected and not the object itself. This is fine but because of that difference you can't simply set
$scope.selected = 2 //assuming 2 is the value coming from your database
because the value '2' does not exist in your option array. The Object with an ID of 2 does.
If you can always guarantee the options you have in the option array are from 1-n and in that order, you can accomplish this by simply using this instead:
$scope.options = [
{ id: 1, label: "My label" },
{ id: 2, label: "My label 2" }
];
var selectedIdFromDatabase = 2;
$scope.selected = $scope.options[selectedIdFromDatabase-1];
If you can't make that guarantee (and even if you can for now, it may not be a good idea to make that assumption in your code) you'll need iterate over the array of objects you have to identify the object with an ID of the selectedId from your database.
The answer to this question has a great write-up about the type of data-processing you'll need to do and a lot more information about javascript objects in general.
I have a cshtml file in which i have following code (a dropdown with data taken from a model)
<div class="controls">
<select ng-model="model.CountryCode" ng-change="countryChanged({{country.ISO316613LetterCode}})">
<option ng-repeat="country in model.Countries" value="{{country.ISO316613LetterCode}}">{{country.CommonName}}</option>
</select>
</div>
And i have this function, in which i detect that a country was chosen from the dropdown
$scope.countryChanged = function(){
var countryDet = _.find($scope.model.CountryDetails, function(cd){
console.log("countryDet");
return cd.CountryCode === $scope.model.Country;
});
if(countryDet){
$scope.model.CountryDetail = countryDet;
// set business properties from country details
$scope.model.DateFormat = countryDet.DefaultDateFormat;
$scope.model.ShortDateFormat = countryDet.DefaultShortDateFormat;
$scope.model.DateFormatJs = countryDet.DefaultJsDateFormat;
$scope.model.LongDateFormat = countryDet.DefaultLongDateFormat;
$scope.model.TaxCode = countryDet.SalesTaxName;
$scope.model.Currency = countryDet.DefaultCurrencySign;
$scope.model.AccSoftwareDateFormat = countryDet.DefaultAccSoftwareDateFormat
$scope.model.WeightSystem = countryDet.DefaultWeightSystem
}
$scope.loadStates();
};
And another function, that should display additional dropdown on web, showing states if the country choosen was USA or AUstralia
$scope.stateVisible = function(){
if($scope.model && $scope.model.CountryDetail){
return $scope.model.CountryDetail.StateVisible;
}
return false;
};
My problem is, that i do not know how to send the selected LetterCode (value of option) to function countryChanged, because, i thought if i do so, then i will be able to easilly load the states into the additional dropdown and show it on site.
Simply use ng-options which will assign the selected model to the ng-model for the <select>. For example
<select ng-model="model.selectedCountry" ng-change="countryChanged()"
ng-options="country.CommonName for country in model.Countries track by country.ISO316613LetterCode">
</select>
Then, your countryChanged() function (and any other controller function) can use $scope.model.selectedCountry which will be a full country object.
Plunker demo ~ http://plnkr.co/edit/tFjvT92B1itmwkRjZIbJ?p=preview
Since you're using $scope for every variable you could use rootScope
https://docs.angularjs.org/api/ng/service/$rootScope
for passing the data.