Track by index doesnt reset after changing selection - angularjs

i have a cascading select option, and is working well, the problem is that when i change the first selected option, in the second selection option (subcategory), it keeps the index. So case i change the category (first select), in the second selection it goes to the option position that it was.
For better understanding, please check this example i made and try changin the options. You will notice that in the second selec option keeps the position index that had in the previous category selected. It doesnt starts to 0 when changing the category.
Link: http://jsfiddle.net/Fqfg3/28/
Js:
var app = angular.module('app', []);
app.controller('PeopleCtrl', function ($http,$scope) {
vm = this;
vm.options = [
{
"_id": "1",
"label": "Category 1",
"childs": [
"Category 1 -> Subcategory 1",
"Category 1 -> Subcategory 2",
"others"
]
},
{
"_id": "2",
"label": "Category 2",
"childs": [
"Category 2 -> Subcategory 1",
"Category 2 -> Subcategory 2",
"others"
]
},
{
"_id": "3",
"label": "Category 3",
"childs": [
"Category 3 -> Subcategory 1",
"Category 3 -> Subcategory 2",
"others"
]
}];
});
html:
<div ng-app="app" ng-controller="PeopleCtrl as ctrl" class="container">
{{ctrl.options}}
<div class="form-group question-wrapper">
<select class="form-control"
name="category"
ng-options="option.label for option in ctrl.options track by option._id"
ng-model="ctrl.supportMail.selected">
</select>
</div>
<div class="form-group question-wrapper">
<select id="sub" class="form-control"
name="subcategory"
>
<option ng-repeat="child in ctrl.supportMail.selected.childs track by $index">{{child}}</option>
</select>
</div>
</div>

You can use ng-change in main select to reset the subselect to default.
Here's is a demonstration working:
(function() {
"use strict";
angular.module('app', [])
.controller('mainCtrl', function() {
var vm = this;
vm.options = [
{
"_id":"1",
"label":"Category 1",
"childs":[
"Category 1 -> Subcategory 1",
"Category 1 -> Subcategory 2",
"others"
]
},
{
"_id":"2",
"label":"Category 2",
"childs":[
"Category 2 -> Subcategory 1",
"Category 2 -> Subcategory 2",
"others"
]
},
{
"_id":"3",
"label":"Category 3",
"childs":[
"Category 3 -> Subcategory 1",
"Category 3 -> Subcategory 2",
"others"
]
}
];
vm.reset_subSelect = function() {
vm.supportMail.child = vm.supportMail.selected.childs[0];
}
});
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl as ctrl">
<div class="container">
<div class="form-group question-wrapper">
<select class="form-control" name="category" ng-options="option.label for option in ctrl.options track by option._id" ng-model="ctrl.supportMail.selected" ng-change="ctrl.reset_subSelect()" ng-init="ctrl.supportMail.selected = ctrl.options[0]">
</select>
</div>
<div class="form-group question-wrapper">
<select class="form-control" id="sub" name="subcategory" ng-options="child for child in ctrl.supportMail.selected.childs" ng-model="ctrl.supportMail.child" ng-init="ctrl.supportMail.child = ctrl.supportMail.selected.childs[0]">
</select>
</div>
</div>
</body>
</html>
I hope it helps.

By adding an ng-model to your subcategory I was able to resolve the issue you can see the example here
Hope this helps.

Related

angular js filter inside ng-change

my data template looks like this,
scope.items=[{"name:"John","score":1},{"name":"Rick","score":5},{"name":"Peter","score":2}]
I have a select box with values 0,1,2,3,4,5 and would like to filter items object based on score value selected in dropdown
scope.scores= [
{
"name":"condition 0",
"value":"0"
},
{
"name":"condition 1",
"value":"1"
},
{
"name":"condition 2",
"value":"condition 2"
},
{
"name":"condition 3",
"value":"3"
},
{
"name":"condition 4",
"value":"4"
},
{
"name":"condition 5",
"value":"5"
}
]
HTML
<select id="scoreS" ng-model="score" ng-change="updateScore()">
<option
ng-repeat="score in scores"
value="{{score.value}}">{{score.name}}</option>
</select>
So when i select condition 0 from my dropdown box I need to filter items to show only those objects matching score(key) 0 and when I select 1 from the drop down , match only items having score(key) 1 and so on. how do you do this inside updateScore() function ?
Try like this. it's better use ng-options instead of ng-repeat in drop-down
var app = angular.module('anApp', []);
app.controller('aCtrl', function($scope) {
$scope.items=[
{"name":"John","score":1}
,{"name":"Rick","score":5}
,{"name":"Peter","score":2}
]
$scope.scores= [
{
"name":"condition 0",
"value":"0"
},
{
"name":"condition 1",
"value":"1"
},
{
"name":"condition 2",
"value":"2"
},
{
"name":"condition 3",
"value":"3"
},
{
"name":"condition 4",
"value":"4"
},
{
"name":"condition 5",
"value":"5"
}
]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="anApp" ng-controller="aCtrl as vm">
<select id="scoreS" ng-model="score" ng-options="score.value as score.name for score in scores ">
</select>
<div ng-repeat="item in items| filter:{score:score}">
<span>{{item.name}}</span>
</div>
</div>
use filter option to filter the data according to drop down
<div ng-repeat="item in items | filter :score">
Demo
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.scores= [
{
"name":"condition 0",
"value":"0"
},
{
"name":"condition 1",
"value":"1"
},
{
"name":"condition 2",
"value":"2"
},
{
"name":"condition 3",
"value":"3"
},
{
"name":"condition 4",
"value":"4"
},
{
"name":"condition 5",
"value":"5"
}
]
$scope.items=[{"name":"John","score":1},{"name":"Rick","score":5},{"name":"Peter","score":2}]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select id="scoreS" ng-model="score" ng-change="updateScore()">
<option ng-repeat="score in scores" value="{{score.value}}">{{score.name}}</option>
</select>
<div ng-repeat="item in items | filter :score">
{{item.name}}= {{item.score}}
</div>
</div>

Update <select> tag inside ng-if in angularjs

I would like to update the list of states on selection of country. I have researched a bit into this where it was recommended to use $parent as ng-if does not work on controller scope.But that too is not working for me.
Can someone please help me understand how to get the values into state select control.
Also I would also like to know what if there are multiple ng-if in my HTML. (again nested $parent.$parent.$parent... is not working)
Plunker Link : Plunker Link
"use strict";
var app = angular.module("app", []);
function CountriesController($scope) {
$scope.condition = true;
$scope.countries = [{
"name": "USA",
"id": 1
},{
"name": "Canada",
"id": 2
}];
$scope.states = [{
"name": "Alabama",
"id": 1,
"countryId": 1
}, {
"name": "Alaska",
"id": 2,
"countryId": 1
}, {
"name": "Arizona",
"id": 3,
"countryId": 1
}, {
"name": "Alberta",
"id": 4,
"countryId": 2
}, {
"name": "British columbia",
"id": 5,
"countryId": 2
}];
$scope.updateCountry = function(){
$scope.availableStates = [];
angular.forEach($scope.states, function(value){
if(value.countryId == $scope.country.id){
$scope.availableStates.push(value);
}
});
}
}
<!DOCTYPE html>
<html data-ng-app="app">
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body data-ng-controller="CountriesController">
<div ng-if="condition">
<select data-ng-model="country" data-ng-options="country.name for country in countries" data-ng-change="updateCountry()">
<option value="">Select country</option>
</select>
<br>
<select data-ng-model="state" data-ng-options="state.name for state in availableStates">
<option value="">Select state</option>
</select>
<br> Country: {{country}}
<br> State: {{state}}
</div>
</body>
</html>
Instead of making a separate list, you can use your country list by filtering
filter: {countryId: $parent.country.id}
"use strict";
var app = angular.module("app", []);
function CountriesController($scope) {
$scope.condition = true;
$scope.countries = [{
"name": "USA",
"id": 1
},{
"name": "Canada",
"id": 2
}];
$scope.states = [{
"name": "Alabama",
"id": 1,
"countryId": 1
}, {
"name": "Alaska",
"id": 2,
"countryId": 1
}, {
"name": "Arizona",
"id": 3,
"countryId": 1
}, {
"name": "Alberta",
"id": 4,
"countryId": 2
}, {
"name": "British columbia",
"id": 5,
"countryId": 2
}];
$scope.updateCountry = function(){
$scope.availableStates = [];
angular.forEach($scope.states, function(value){
if(value.countryId == $scope.country.id){
$scope.availableStates.push(value);
}
});
}
}
<!DOCTYPE html>
<html data-ng-app="app">
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body data-ng-controller="CountriesController">
<div ng-if="condition">
<select data-ng-model="country" data-ng-options="country.name for country in countries" data-ng-change="">
<option value="">Select country</option>
</select>
<br>
<select data-ng-model="state" data-ng-options="state.name for state in states | filter:{countryId: country.id}:true">
<option value="">Select state</option>
</select>
<br> Country: {{country}}
<br> State: {{state}}
</div>
</body>
</html>
Here is simplest way to init selected option:
for blank form, just init with option value that you want (don't forget the double single quotes)
<select ng-model="$ctrl.data.userlevel" ng-init="$ctrl.data.userlevel='0'">
<option value="0">User</option>
<option value="1">Admin</option>
</select>
for loaded data form, just init using that loaded model data, like below:
<select ng-model="$ctrl.data.userlevel" ng-init="$ctrl.data.userlevel=''+$ctrl.data.userlevel">
<option value="0">User</option>
<option value="1">Admin</option>
</select>
i think, init value should be string. so they need to concat with double single quotes.

Display Groupname with selected item on Dropdown using angularjs?

This is my Code
var app = angular.module('myExample', []);
function myCtrl($scope) {
$scope.myOptions = [{
"id": 106,
"group": "Employee",
"label": "Id"
},{
"id": 107,
"group": "Employee",
"label": "Name"
},{
"id": 110,
"group": "Department",
"label": "Id"
}];
$scope.getSelectedField=function(){
//$scope.myOption=$scope.myOption;
alert($scope.myOption);
};
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="myCtrl">
<select
ng-model="myOption"
ng-options="value.group+'.'+value.label as value.label group by value.group for value in myOptions" ng-change="getSelectedField()" >
<option>--</option>
</select>
<div>
selected value: {{myOption}}
</div>
</div>
The above code selected Item display on dropdown , But I want to display Groupname with Selected Item on Dropdown.for example when user select id now display 'Employee.id' on Dropdown.
Try
Here value.group+'.'+value.label will display on dropdown. Before you were displaying only value.label.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="myCtrl">
<select
ng-model="myOption"
ng-options="value.group+'.'+value.label as value.group+'.'+value.label group by value.group for value in myOptions" ng-change="getSelectedField()" >
<option>--</option>
</select>
<div>
selected value: {{myOption}}
</div>
</div>

ng-change not firing when switching between ng-includes

My domain is such that Bars have Groups. The following code allows the user to pick a Bar (outputted to {{selected.bar.name}}). Users are to choose a Bar.
If a Group only has one Bar then the Bar is presented at the top level (step-0), otherwise the user can drill down into the Group and select the Bar from there (step-1).
In the below code, Bar 1 and Bar 2 are their only ones in their group, whilst Bar 3 and Bar 4 share a group, Group 3.
Everything works well apart from the following sequence:
Select Group 3
Select any Bar
Click Previous
Select any other Bar
Selecting Group 3 again does not take you to step-1 again; the ng-change event is not fired.
(function(ng) {
'use strict';
ng.module('awesome', [])
.controller('BarController', [
'$scope',
function($scope) {
$scope.bars = [{
"id": 1,
"name": "Bar 1",
"group": "Group 1"
}, {
"id": 2,
"name": "Bar 2",
"group": "Group 2"
}, {
"id": 3,
"name": "Bar 3",
"group": "Group 3"
}, {
"id": 4,
"name": "Bar 4",
"group": "Group 3"
}];
$scope.currentTab = 'step-0';
$scope.previousTab = null;
$scope.goBack = function() {
$scope.currentTab = $scope.previousTab;
$scope.previousTab = null;
}
$scope.groupedBars = _.groupBy($scope.bars, 'group');
$scope.selected = {}
$scope.availableGroupedBars = $scope.groupedBars;
$scope.availableBars = $scope.bars;
$scope.groupSelected = function(group) {
console.log('groupSelected');
$scope.currentTab = 'step-1';
$scope.previousTab = 'step-0';
$scope.availableBars = group;
}
}
]);
})(window.angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.1/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="awesome">
<div ng-controller="BarController">
<div ng-include="currentTab"></div>
Selected bar name: {{selected.bar.name}}
<button ng-show="previousTab" ng-click="goBack()">Previous</button>
</div>
<script type="text/ng-template" id="step-0">
<ul>
<li ng-repeat="(key, group) in availableGroupedBars">
<label ng-switch="group.length">
<span ng-switch-default>{{key}}</span>
<input ng-switch-default type="radio" name="group" ng-model="selected.group" ng-value="group" ng-change="groupSelected(selected.group)" />
<span ng-switch-when="1">{{group[0].name}}</span>
<input ng-switch-when="1" type="radio" name="group" ng-model="selected.bar" ng-value="group[0]" />
</label>
</li>
</ul>
</script>
<script type="text/ng-template" id="step-1">
<ul>
<li ng-repeat="bar in availableBars">
<label>
{{bar.name}}
<input type="radio" name="bar" ng-model="selected.bar" ng-value="bar" required />
</label>
</li>
</ul>
</script>
</div>
How can I make the ng-change event for Group 3 fire once returning to step-0?
The change event is not fired because nothing changes. You only have one group and that group is still selected when you go back. It stays selected forever, i.e the value of $scope.selected.group never changes, regardless of what radio button you choose.
The ngChange expression is only evaluated when a change in the input value causes a new value to be committed to the model.
I strongly suggest to rethink your approach. If you don't want to then you can add an ng-change to your bars in step-0 and clear $scope.selected.group whenever a bar is selected.
$scope.clearGroup = function() {
$scope.selected.group = null;
};
<input ng-switch-when="1" type="radio" name="group"
ng-model="selected.bar" ng-value="group[0]"
ng-change="clearGroup()" />

Data binding between radio button and other elements not working as expected

I have following JSON with answers:
And i want to submit this to database only one of the answer can have "IS_CORRECT" flag with value "Y:
"Answers": [
{ "ANSWER_ID": 5, "DESCRIPTION": "Answer 3", "IS_CORRECT": "N" },
{ "ANSWER_ID": 4, "DESCRIPTION": "Answer 2", "IS_CORRECT": N },
{ "ANSWER_ID": 3, "DESCRIPTION": "Answer 1", "IS_CORRECT": "N" }
]
In my html i use ng-repeat to loop over my answers and i create a radio button for each.
<div class="control-group" ng-repeat="answer in Answers>
<input type="radio" ng-model="answer.IS_CORRECT" value="Y" name="answer"/>
</div>
My problem is that when i check Answer_id 5 as correct it updates "IS_CORRECT" field from my model to "Y" but it does not update AnsWer 4 and 3 "IS_CORRECT to 'N'.
Can you please give me some suggestions
You are using radio buttons as checkboxes. Better approach is to save current value:
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.js"></script>
</head>
<body ng-app="testApp">
<div ng-controller="controller">
<div class="control-group" ng-repeat="answer in answers">
<label>
{{answer.DESCRIPTION}}
<input type="radio" ng-model="$parent.correctAnswer" ng-value="answer" name="correct_answer">
</label>
</div>
Correct Answer: {{correctAnswer.DESCRIPTION}}
</div>
</body>
<script>
var app = angular.module('testApp', []);
app.controller('controller', function($scope) {
$scope.answers = [
{ "ANSWER_ID": 5, "DESCRIPTION": "Answer 3"},
{ "ANSWER_ID": 4, "DESCRIPTION": "Answer 2"},
{ "ANSWER_ID": 3, "DESCRIPTION": "Answer 1"}
];
$scope.correctAnswer = $scope.answers[1];
});
</script>
</html>

Resources