AngularJS second dropdown does not update when first dropdown changes - angularjs

I'm creating a search page where the user can search for data using pre-selected search criteria listed in the first drop-down. In the example below those criteria are 'First Name', 'Country' and 'Nationality'.
When the user selects Country or Nationality, a second drop-down appears to select one of the countries/nationalities. To fill this drop-down i use ng-options with a variable inside that points to a string defined in the controller.
But when one of those two options is selected and you want to switch to the other, the second drop-down does not get updated. The value inside ngOptions does get updated in the HTML, just the data inside the dropdown isn't.
When you select 'First Name' in between there is no issue. Does anyone know what I can use so the values inside the second dropdown gets updated?
Below is my code and a working plunker: http://plnkr.co/edit/LYpOdoLpgiMeHxlGzmub?p=preview
var myApp = angular.module('myApp', []);
myApp.controller("SomeController", function($scope) {
var vm = this;
vm.search = {id:0, criteria: {}, value: ''};
vm.referenceData = {
countries: [
{COUNTRY_ID:1, COUNTRY_NAME: 'UNITED KINGDOM'},
{COUNTRY_ID:2, COUNTRY_NAME: 'AUSTRALIA'},
{COUNTRY_ID:3, COUNTRY_NAME: 'SOUTH AFRICA'},
{COUNTRY_ID:4, COUNTRY_NAME: 'NETHERLANDS'},
],
nationalities: [
{NATIONALITY_ID: 1, NATIONALITY_NAME: "BRITISH"},
{NATIONALITY_ID: 2, NATIONALITY_NAME: "AUSTRALIAN"},
{NATIONALITY_ID: 3, NATIONALITY_NAME: "SOUTH AFRICAN"},
{NATIONALITY_ID: 4, NATIONALITY_NAME: "DUTCH"},
]
};
vm.criteriaList = [
{ name: 'First Name', key: 'FIRST_NAME'},
{ name: 'Country', key: 'COUNTRY_ID', options:'o.COUNTRY_ID as o.COUNTRY_NAME for o in ctrl.referenceData.countries' },
{ name: 'Nationality', key: 'NATIONALITY', options:'o.NATIONALITY_ID as o.NATIONALITY_NAME for o in ctrl.referenceData.nationalities' }
];
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp" ng-controller="SomeController as ctrl">
<p>Criteria:</p>
<select ng-model="search.criteria" ng-change="search.value = ''" ng-options="criteria as criteria.name for criteria in ctrl.criteriaList">
<option value="">- Select Criteria -</option>
</select>
<p>Value:</p>
<!-- TEXT INPUT -->
<input type="text" ng-model="search.value" placeholder="Search Value" ng-if="!search.criteria.options" />
<!-- DROPDOWN INPUT -->
<select ng-model="search.value" ng-if="search.criteria.options" ng-options="{{search.criteria.options}}"></select>
</html>

This is an easy fix you just need a variable that can if out the second dropdown everytime you switch. The dom needs something to force it to refresh since there isnt a scope.$apply happening.
Plunker Working
Try this:
var myApp = angular.module('myApp', []);
myApp.controller("SomeController", function($scope, $timeout) {
var vm = this;
vm.somVal = false; ///ADD THIS
vm.search = {id:0, criteria: {}, value: ''};
vm.triggerSomeVal = function(){ ///ADD THIS
vm.someVal = true;
$timeout(function(){vm.someVal = false}, 100)
};
vm.referenceData = {
countries: [
{COUNTRY_ID:1, COUNTRY_NAME: 'UNITED KINGDOM'},
{COUNTRY_ID:2, COUNTRY_NAME: 'AUSTRALIA'},
{COUNTRY_ID:3, COUNTRY_NAME: 'SOUTH AFRICA'},
{COUNTRY_ID:4, COUNTRY_NAME: 'NETHERLANDS'},
],
nationalities: [
{NATIONALITY_ID: 1, NATIONALITY_NAME: "BRITISH"},
{NATIONALITY_ID: 2, NATIONALITY_NAME: "AUSTRALIAN"},
{NATIONALITY_ID: 3, NATIONALITY_NAME: "SOUTH AFRICAN"},
{NATIONALITY_ID: 4, NATIONALITY_NAME: "DUTCH"},
]
};
vm.criteriaList = [
{ name: 'First Name', key: 'FIRST_NAME'},
{ name: 'Country', key: 'COUNTRY_ID', options:'o.COUNTRY_ID as o.COUNTRY_NAME for o in ctrl.referenceData.countries' },
{ name: 'Nationality', key: 'NATIONALITY', options:'o.NATIONALITY_ID as o.NATIONALITY_NAME for o in ctrl.referenceData.nationalities' }
];
});
<p>Criteria:</p>
<select ng-model="search.criteria" ng-change="search.value = ''; ctrl.triggerSomeVal()" ng-options="criteria as criteria.name for criteria in ctrl.criteriaList">
<option value="">- Select Criteria -</option>
</select>
<p>Value:</p>
<!-- TEXT INPUT -->
<input type="text" ng-model="search.value" placeholder="Search Value" ng-if="!search.criteria.options" />
<!-- DROPDOWN INPUT ADD !someVal-->
<select ng-model="search.value" ng-if="search.criteria.options && !ctrl.someVal" ng-options="{{search.criteria.options}}"></select>

Related

AngularJS ng-options from nested array

Is it possible to use nested for-loops in an ng-options expression?
The following python-style syntax does not work in AngularJS v1.5.8:
ng-options="user for group in userGroups for user in group.userNames"
angular.module('myApp', [])
.controller('LoginController', ['$scope', function ($scope) {
$scope.userGroups = [{
groupId: 1,
groupName: 'owner',
userNames: [
'John',
'Mary'
]
},
{
groupId: 2,
groupName: 'admin',
userNames: [
'Fred'
]
},
{
groupId: 3,
groupName: 'client',
userNames: [
'Company1',
'Company2',
'Company3'
]
}
];
$scope.selectedUserName = null;
$scope.$watch('selectedUserName', function(newValue, oldValue) {
console.log('selectedUserName changed from', oldValue, 'to', newValue);
});
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="myApp" ng-controller="LoginController">
<select
id="form-login-user"
ng-model="selectedUserName"
ng-options="user for group in userGroups for user in group.userNames"
>
<option></option>
</select>
</div>

Angularjs:radio button is not aligning in one line using the ng-repeat,tr,td

I have written simple angularjs code which will have the multiple radio buttons.I have implemented it using the ng-repeat,tr,td.
Below is the code,
<html ng-app="plunker">
<head>
<script data-require="angular.js#1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
</head>
<body ng-controller="MainCtrl">
<table>
<tr ng-repeat="subscription in entities">
<td>
<input type="radio" ng-model="subscription.checked" ng-value="true" ng-click="updateSelection($index, entities)" />{{subscription.name}}
</td>
</tr>
</table>
</body>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $http, $location, $window) {
$scope.entities = [{
name: 'Last Week',
id: 1,
checked: false
}, {
name: 'Last Month',
id: 2,
checked: false
}, {
name: 'Last year',
id: 3,
checked: false
},
{
name: 'Last 3 months',
id: 4,
checked: false
},
{
name: 'Last 6 months',
id: 5,
checked: false
},
{
name: 'Last 9 months',
id: 6,
checked: false
}
]
$scope.updateSelection = function(position, entities) {
angular.forEach(entities, function(subscription, index) {
if (position != index)
subscription.checked = false;
else {
console.log(subscription.id);
$window.location.href = "/view_report/?q=" + subscription.id;
}
});
};
});
</script>
The code should display the all the buttons in to the single horizontal line because td is inside tr.However all the buttons are displayed in new row/line.
Please help.
Just move your ng-repeat to TD tag. Since you have in TR tag, it will keep repeating the TR also.
<html ng-app="plunker">
<head>
<script data-require="angular.js#1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
</head>
<body ng-controller="MainCtrl">
<table>
<tr>
<td ng-repeat="subscription in entities">
<input type="radio" ng-model="subscription.checked" ng-value="true" ng-click="updateSelection($index, entities)" />{{subscription.name}}
</td>
</tr>
</table>
</body>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $http, $location, $window) {
$scope.entities = [{
name: 'Last Week',
id: 1,
checked: false
}, {
name: 'Last Month',
id: 2,
checked: false
}, {
name: 'Last year',
id: 3,
checked: false
},
{
name: 'Last 3 months',
id: 4,
checked: false
},
{
name: 'Last 6 months',
id: 5,
checked: false
},
{
name: 'Last 9 months',
id: 6,
checked: false
}
]
$scope.updateSelection = function(position, entities) {
angular.forEach(entities, function(subscription, index) {
if (position != index)
subscription.checked = false;
else {
console.log(subscription.id);
$window.location.href = "/view_report/?q=" + subscription.id;
}
});
};
});
</script>
Also, find the plunker link for your code:
https://plnkr.co/edit/tiLFg8r8Xk8aR65aNcG9?p=preview

How to pre-select values in multi select input with AngularJS

I have the following HTML:
<div ng-controller="CreateSpreadsheetCtrl as csCtrl" ng-init="csCtrl.init()">
<select multiple="multiple" style="height:100px;" class="form-control"
ng-model="csCtrl.Template.BusinessUnitMappings"
ng-options="department as department.LocalizedName for department in csCtrl.DepartmentMasters">
</select>
</div>
Inside the CreateSpreadsheetCtrl.init(), we are loading an array called "DepartmentMasters" (csCtrl.DepartmentMasters) which contains a list of objects (e.g. {Id:1, Name: "Department 1" }, {Id:2, Name: "Department 2" }).
Also in the init() method, we load this "csCtrl.Template" object, which has a property inside it called "BusinessUnitMappings" (csCtrl.Template.BusinessUnitMappings), which is an array of DepartmentMaster objects.
With the above code, it binds correctly to the model and when you change the selections, csCtrl.Template.BusinessUnitMappings is bound correctly.
However, when csCtrl.Template.BusinessUnitMappings is pre-loaded with an existing array of objects, it doesn't select it in the UI when the page initially loads.
Change the expression to :
ng-options="department as department.Name for department in csCtrl.DepartmentMasters track by department.Id"
Working Demo :
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl',function($scope) {
var ctrl = this;
ctrl.DepartmentMasters = [
{Id:1, Name: "Department 1" },
{Id:2, Name: "Department 2" },
{Id:3, Name: "Department 3" },
{Id:4, Name: "Department 4" },
{Id:5, Name: "Department 5" }
];
ctrl.Template = {
"BusinessUnitMappings" : [
{Id:2, Name: "Department 2" },
{Id:3, Name: "Department 3" }
]
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl as csCtrl">
<select multiple="true" style="height:100px;" class="form-control"
ng-model="csCtrl.Template.BusinessUnitMappings"
ng-options="department as department.Name for department in csCtrl.DepartmentMasters track by department.Id"></select>
</div>

Preselected values for angular-schema-form

Does angular-schema-form have a method to show preselected values?
When the titleMap on the select will set an integer, preselected values will show. But if it will set an object, I found no way of showing the correct name.
Is there anything to tie the object to, like with ng-options where you can set an attribute to compare them with the "track by" clause?
ng-options="option as option.name for option in array track by option.id"
In my example code, cats1 will set an object, cats2 will set an integer.
HTML:
<body>
<div ng-controller="MainCtrl">
<div class="login-container">
<form name="myForm"
sf-schema="schema"
sf-form="form"
sf-model="model">
</form>
</div>
</div>
</body>
Controller:
app.controller('MainCtrl', ['$scope', function ($scope) {
$scope.form = [
{
key: 'cats1',
type: 'select',
titleMap: [
{value: {id: 0, name: "Leopard"}, name: "Leopard"},
{value: {id: 1, name: "Tiger"}, name: "Tiger"}
]
},
{
key: 'cats2',
type: 'select',
titleMap: [
{value: 0, name: "Leopard"},
{value: 1, name: "Tiger"}
]
}
];
$scope.schema = {
"type": "object",
"properties": {
"cats1": {
"title": "Cats",
"type": "object"
},
"cats2": {
"title": "Cats",
"type": "number"
}
}
};
$scope.model = {cats1: {id: 1, name: "Tiger"}, cats2: 1};
}]);
Here is a plunkr:
https://plnkr.co/edit/0hK5Hrc9GXklfRwa6fjE?p=preview

Ng-Options for objects in an array

Here I have a select, where I want to repeat the contacts on the supplier.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="AppCtrl">
Hello {{name}}
<div ng-repeat="supplier in suppliers">
{{supplier.name}}
<select ng-options="contact.id as contact.name for contact in supplier.contacts">
</select>
</div>
</div>
<script>
var app = angular.module('app',[]);
//app.directive('appDirective', function() {});
//app.factory('appService', function() {});
app.controller('AppCtrl', ['$scope', function($scope){
$scope.name = "dave";
$scope.suppliers = [
{id: 0, name: "dave", contacts : [
{id: 0, name: 'c1'},
{id: 1, name: 'c2'},
{id: 2, name: 'c3'},
{id: 3, name: 'c4'},
]},
{id: 1, name: "Steve", contacts : [
{id: 0, name: 'c1'},
{id: 1, name: 'c2'},
{id: 2, name: 'c3'},
{id: 3, name: 'c4'},
]}
]
}]);
</script>
Here I have the controller.
How come this doesn't seem to work?
http://jsfiddle.net/gnosticdave/091vpadb/1/
contacts is part of each supplier - so your array is actually supplier.contacts
select ng-options="contact.id as contact.name for contact in supplier.contacts"
^^^^^^^^^^^^^^^^^^^^
Also, ngOptions needs an ngModel
Demo: http://jsfiddle.net/091vpadb/3/
Change:
<select ng-options="contact.id as contact.name for contact in contacts">
to:
<select ng-options="contact.id as contact.name for contact in supplier.contacts">

Resources