I am very new to AngularJS and after watching some pluralsight videos I decided to build a simple web page using it.
The page should initially load with one select box which is populated by an ajax request (this contains all of the data). Then, based on the value selected, a new select element may need to be created containing the child data. This will continue to happen until an option is selected that has no child ids. The format of data I get back from the api is as follows.
[ { "ChildIds" : [ ],
"Id" : "1",
"Name" : "Top Level",
"ParentId" : null
},
{ "ChildIds" : [ "51" ],
"Id" : "22",
"Name" : "LevelA - 1",
"ParentId" : "1"
},
{ "ChildIds" : [ "38",
"26"
],
"Id" : "24",
"Name" : "LevelA - 2",
"ParentId" : "1"
},
{ "ChildIds" : [ ],
"Id" : "38",
"Name" : "LevelB - 1",
"ParentId" : "24"
},
{ "ChildIds" : [ ],
"Id" : "26",
"Name" : "LevelB - 2",
"ParentId" : "24"
},
{ "ChildIds" : [ ],
"Id" : "51",
"Name" : "LevelB - 3",
"ParentId" : "22"
},
{ "ChildIds" : [ "43",
"21"
],
"Id" : "36",
"Name" : "LevelC - 1",
"ParentId" : "26"
},
{ "ChildIds" : [ ],
"Id" : "43",
"Name" : "LevelD - 1",
"ParentId" : "36"
},
{ "ChildIds" : [ ],
"Id" : "21",
"Name" : "LevelD -2",
"ParentId" : "36"
}
]
I have managed to get this working by using hard coded select elements but want to make this dynamic.
Html
<div class="container">
<div ng-controller="organisationalUnitCtrl">
<select class="form-control" ng-model="root" ng-options="ou.Name for ou in ous | filter:{ParentId:'!'}">
<option value="">-- choose organisation unit --</option>
</select>
<select class="form-control" ng-model="child" ng-options="ou.Name for ou in ous | filter:{ParentId:root.Id}">
<option value="">-- choose organisation unit --</option>
</select>
<select class="form-control" ng-model="child2" ng-options="ou.Name for ou in ous | filter:{ParentId:child.Id}">
<option value="">-- choose organisation unit --</option>
</select>
<select class="form-control" ng-model="child3" ng-options="ou.Name for ou in ous | filter:{ParentId:child2.Id}">
<option value="">-- choose organisation unit --</option>
</select>
</div>
</div>
Controller
bristowRiskApp.controller('organisationalUnitCtrl',
function organisationalUnitCtrl($scope, organisationalUnitData) {
$scope.ous = organisationalUnitData.getOrganisationalUnit();
}
);
Service
bristowRiskApp.factory('organisationalUnitData', function ($http, $q) {
return {
getOrganisationalUnit: function () {
var deferred = $q.defer();
$http({ method: 'GET', url: 'http://localhost:53995/api/organisationalunit' }).
success(function (data, status, headers, config) {
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
}
});
I have read that you should not manipulate the DOM in the controller. So, I am guessing that I should create a directive for my select element that listens for onChange events and creates the new select element? How do I do this? Are there any examples out there that I could learn from?
One other issue I face with my hard coded example is that changing a value in a select only ripples to the next combo. For example, if values were selected in all four select boxes, changing a value in the second one would correctly reset the third box but the fourth will still contain the selected option. I thought the change would be rippled all the way down.
Thanks
Steven
Let me know if/why this doesn't work and I'll fix it accordingly. I think the key fact is in the options repeater you weren't using the syntax to specify the ID of the option - you were just doing its label.
http://jsfiddle.net/KVdqb/
HTML
<div ng-app="bristowRiskApp" ng-controller="organisationalUnitCtrl">
$scope.selections: <pre>{{ selections | json }}</pre>
<div ng-repeat="i in range(selections.length - 1)">
<cascade-select data="data" parent-id="selections[i]" selected-id="selections[i + 1]"></cascade-select>
</div>
</div>
Javascript
var bristowRiskApp = angular.module('bristowRiskApp', []);
bristowRiskApp.controller('organisationalUnitCtrl',
function organisationalUnitCtrl($scope) {
$scope.data = [ /* ... */ ];
$scope.selections = [ null, null ];
$scope.$watch('selections', function (value) {
if (value[value.length - 1] !== null || value.length < 2) {
value.push(null);
} else {
var index = value.indexOf(null, 1);
if (0 < index && index < value.length - 1) {
$scope.selections = value.slice(0, index);
}
}
}, true);
// Helper function.
$scope.range = function (n) {
var result = [];
for (var i = 0 ; i <n; i++) {
result.push(i);
}
return result;
};
});
bristowRiskApp.directive('cascadeSelect', function () {
return {
restrict: 'E',
replace: true,
scope: {
parentId: '&',
selectedId: '=',
data: '='
},
template: '<select ng-show="(data | filter:byId).length > 0" ng-model="selectedId" ng-options="d.Id as d.Name for d in data | filter:byId"><option value="">-- choose organisation unit --</option></select>',
link: function (scope, element, attrs) {
scope.byId = function (d) {
return d.ParentId === scope.parentId();
};
}
}
});
Related
I am using ng-repeat for list of options.In that list I have ID and DESCRIPCION,when select one option am appending ID and DESCRIPCION to ng-model like as Object.In controller part need to ceperate ID and DESCRIPCION.I used below code but getting undefined in alert when select one option.
http://jsfiddle.net/KN9xx/1237/
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.10.0/js/bootstrap-select.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.10.0/css/bootstrap-select.min.css" rel="stylesheet" />
<div ng-app="myapp" ng-controller="FirstCtrl">
<select class="form-control selectpicker" data-live-search="true" ng-model="subappData" ng-change="getSubApplicationDetails(subappData)" id="subapplicationid" style="height: 21px;width: 300px;-moz-margin-start: 132px;margin-left: 138px;margin-top: 2px;-moz-margun-start: 132px;">
<option value="">Select</option>
<option ng-repeat='subapp in subapplicationList | filter:query' data-select-watcher data-last="{{$last}}" value = "{{subapp}}"> {{subapp.ID}} - {{subapp.DESCRIPCION}} </option>
</select>
</div>
controller.js:
var myapp = angular.module('myapp', []);
myapp.controller('FirstCtrl', function ($scope) {
$scope.subapplicationList = [
{"ID" : 9 ,"DESCRIPCION" : "a" },
{"ID" : 1 ,"DESCRIPCION" : "b" },
{"ID" : 2 ,"DESCRIPCION" : "c" },
{"ID" : 3 ,"DESCRIPCION" : "d" },
{"ID" : 4 ,"DESCRIPCION" : "e" },
{"ID" : 5 ,"DESCRIPCION" : "f" },
{"ID" : 6 ,"DESCRIPCION" : "g" },
{"ID" : 7 ,"DESCRIPCION" : "h" },
{"ID" : 8 ,"DESCRIPCION" : "i" }
];
$scope.getSubApplicationDetails = function(subappData) {
alert(JSON.stringify(subappData));
};
});
myapp.directive('selectWatcher', function ($timeout) {
return {
link: function (scope, element, attr) {
var last = attr.last;
if (last === "true") {
$timeout(function () {
$(element).parent().selectpicker('val', 1);
$(element).parent().selectpicker('refresh');
});
}
}
};
});
Try like this
$scope.getSubApplicationDetails = function(subappData) {
var object = JSON.parse(subappData)
console.log(object.ID);
};
I have a json response as given below from backend
JSON:
{
"json": {
"response": {
"servicetype": "1",
"functiontype": "10011",
"statuscode": "0",
"statusmessage": "Success",
"data":{
"roleid": 36,
"rolename": "Product Managers",
"divisionlabel": "Department ",
"subdivisionlabel": "Category",
"roleinformation": {
"QA": [
{
"White Box Testing": 10
}
]
}
},
{
"roleid": 38,
"rolename": "Managers",
"divisionlabel": "Department ",
"subdivisionlabel": "Category",
"roleinformation": {
"QA": [
{
"Black Box Testing": 10
}
]
}
}
}
}
}
}
I have inserted my role names in a dropdown $scope.model.rolename .
If my rolename is selected as product managers I want to give value of my $scope.maxcount value as "White Box Testing": 10 .It should be dynamic , based on selection the value will change. Now in dropdown if I select Manager the $scoope.maxcount for manager value will change. I have done till dropdown , dont know to handle after it .
JS:
` `UserService.getAssignRoles(json).then(function(response) {
if (response.json.response.statuscode == 0 && response.json.response.statusmessage == 'Success')
{
$scope.model.roles= [], assignrolesArray = [];
assignrolesArray = unasresdata.concat(assresdata);
$scope.model.assignroles = assignrolesArray;
}
});
HTML:
<select class="form-control" name="role"
ng-model="model.rolename"
ng-change="getassignRole(model.rolename)">
<option selected>Select Roles</option>
<option ng-repeat="role in model.assignroles track by $index"
value="{{role.rolename}}">{{role.rolename}}</option>
</select>
<input type = "text" ng-model=$scope.maxcount>
You can pass your model.assignroles and scope value into this getassignRole() function and from that, you can get property and set it to your scope variable.
Do install lodash library and inject it.
HTML
ng-change="getassignRole(model.assignroles, model)"
JS
$scope.getassignRole= function(model.assignroles, rolename){
console.log(model.assignroles);
var test = _.filter(model.assignroles, function(o){
return o.rolename === rolename;
})
console.log(rolename);
console.log(test[0].roleinformation);
};
Sample jsfiddle: https://jsfiddle.net/alpeshprajapati/5kpxzrgf/1/
You can access required property then.
Hope it helps.
Database (.JSON):
{
"permissionLevels" : {
"Admin" : {
"Comment Access" : "value",
"Page Access" : "value",
"Post Access" : "value"
},
"Default" : {
"Comment Access" : "value",
"Page Access" : "value",
"Post Access" : "value"
},
"Template" : {
"Comment Access" : "value",
"Page Access" : "value",
"Post Access" : "value"
}
},
"users" : {
"User 1" : {
"Email" : "user1#gmail.com",
"Name" : "User 1",
"PhotoURL" : "https://lh5.googleusercontent.com/-m1_AWD2hhp0/AAAAAAAAAAI/AAAAAAAAAZY/IhIwoLVwl6U/s96-c/photo.jpg",
"Role" : "Default",
"uid" : "1235"
},
"User 2" : {
"Email" : "user2#gmail.com",
"Name" : "User 2",
"Role" : "Default",
"uid" : "1236"
},
"User 3" : {
"Email" : "user3#gmail.com",
"Name" : "User 3",
"PhotoURL" : "https://lh5.googleusercontent.com/-m1_AWD2hhp0/AAAAAAAAAAI/AAAAAAAAAZY/IhIwoLVwl6U/s96-c/photo.jpg",
"Role" : "Admin",
"uid" : "1237"
}
}
}
HTML:
<table id="table">
<tr>
<th>Name</th>
<th>Email</th>
<th>Permission Level</th>
</tr>
<tr ng-repeat="(key, value) in users">
<td>{{value.Name}}</td>
<td>{{value.Email}}</td>
<td>
<select name="{{key}}">
<option ng-model="key">{{value.Role}}</option>
<option ng-repeat="(permissionLevel, permissions) in permissionLevels.permissionLevels" ng-if="permissionLevel!=value.Role && permissionLevel!='Template'" ng-selected="string">{{permissionLevel}}</option>
</select>
</td>
</tr>
</table><br/>
What I want to do is display a table with each user's name, email and role (permission level). The role for each person should be displayed in a <select></select> tag and the user should be able to change it and click "UPDATE ALL" to save changes. I got the table to display everything properly but, the issue is getting information out of the table and onto the database. This is what I have so far on the table
In case you are wondering, I want it to ignore the "Template" role because it is there to use as a template for later on.
$firebaseArray and $firebaseObject have 3-way data binding. The view, controller, and database.
var ref = firebase.database().ref("users");
// var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/users");
$scope.users = $firebaseArray(ref);
When you click "Update" you need to iterate through and $save all the records that changed roles.
First I would change your select to:
<select name="{{key}}" ng-options="p.value as p.label for p in permissionLevels" ng-model="value.Role">
</select>
Assuming you have an array of roles:
$scope.permissionLevels = [
{
value: "Default",
label: "Default",
},
{
value: "Admin",
label: "Admin",
}
];
Then when clicking "Update" you can call some function:
$scope.update = function() {
for(var i=0; i<$scope.users.length; i++) {
// Saves all
$scope.users.$save(i).then(function(ref) {
// whatever
})
}
}
Reference: $firebaseArray $save
Normally what we do is
...}}_{{$index}}" ng-options="option.serial_no as option.NameRelation for option in fullFamilydetails" ng-model="obj.ch6a_decl_fam_memb_id">
and on Java I am doing
...
familyDetails.put("NameRelation", Emp_FamilyInfoTemp.getName()+"-"+Emp_FamilyInfoTemp.getRelation());
}else{
...
As you see I am handling it on java to show "NAME" - "RELATION" pair as "name of ng-options"
but what I want is to keep NAME and RELATION as different properties in json but show a combination of them while creating ng-options, all and all I want to create the same effect while keeping the properties separate.
Current Sample Json
[{"DOB":"2014-09-03 00:00:00.0","NameRelation":"MaleChildTest-Son","SERIAL_NO":55213,"AGE":"0"},{"DOB":"2014-09-12 00:00:00.0","NameRelation":"FemaleChildTest-Daughter","SERIAL_NO":55216,"AGE":"0"},{"DOB":"2014-09-12 00:00:00.0","NameRelation":"MaleChildTesEmp-Son","SERIAL_NO":55217,"AGE":"0"},{"DOB":"2014-09-12 00:00:00.0","NameRelation":"FemaleChildEmployeeTest-Daughter","SERIAL_NO":55218,"AGE":"0"},{"DOB":"","NameRelation":"Test-Father","SERIAL_NO":55219,"AGE":"0"}]
supposed JSON
[{"DOB":"2014-09-03 00:00:00.0","Name":"MaleChildTest","Relation":"Son","SERIAL_NO":55213,"AGE":"0"}....]
In dropdown I want Name-Relaiton as "name" of options.
DEMO
<select ng-options="option.serial_no as label(option.Name, option.Relation) for option in fullFamilydetails" ng-model="obj"></select>
In your JS:
angular.module("SO29137733", [])
.controller("MainCtrl", function ($scope) {
$scope.fullFamilydetails = [{
"DOB": "2014-09-03 00:00:00.0",
"Name": "MaleChildTest",
"Relation": "Son",
"SERIAL_NO": 55213,
"AGE": "0"
}, {
"DOB": "2014-09-03 00:00:00.0",
"Name": "MaleChildTest",
"Relation": "Son",
"SERIAL_NO": 55213,
"AGE": "0"
}];
$scope.label = function (name, relation) {
return name + "-" + relation;
}
});
Another option:
DEMO
<select>
<option ng-repeat="option in options" value="{{option.serial_no}}">
{{option.name + " "+option.relation}}
</option>
</select>
In your JS:
angular.module("SO29137733", [])
.controller("MainCtrl", function($scope){
$scope.options = [{
serial_no : "123",
name : "hi",
relation: "parent"
},
{
serial_no : "1233",
name : "sa",
relation: "sdf"
}];
})
If you want to show it as single pair of option then do as below,
ng-options="option.serial_no as (option.name+' '+ option.relation) for option in fullFamilydetails"
I am creating a Grid Control in Angular JS. ( I don't want to use ng-grid, smart table, etc for some reason)
Plunkr URL : http://plnkr.co/edit/arkCZcfXTIsW7sFCxisn?p=preview
On top of the table generated, i have populated fields in the combobox so that user is allowed to search on specific columns
or as free search.
As I see From here :
https://docs.angularjs.org/api/ng/filter/filter
For free search, I have used the syntax as {$:Value} and for column based search, {ColName:Value} syntax
However, I am unable to get it to work when I bind the column names to combobox.
I do get static search to work Eg if I write {'Code':"1"}, this works. but if I take "Code" from a combobox, it doesnt work.
Need help on setting dynamic filter.
This one also does not seem to help.
angular filter with dynamic list of attributes to search
This is the HTML
<div ng-controller="MyGrid">
Search in Column
<select ng-model="FilterByColumn" >
<option value="$">All</option>
<option ng-repeat="hdr in headers | orderBy : hdr.displayOrder" ng-show="hdr.isVisible" value="{{hdr.name}}" >
{{hdr.caption}}
</option>
</select>
Value : <input type="text" ng-model="searchKeyword" />
<br />
Remove Sort
<table>
<thead>
<tr>
<th ng-repeat="hdr in headers | orderBy : hdr.displayOrder" ng-show="hdr.isVisible">
{{hdr.caption}}
</th>
</tr>
</thead>
<tbody>
<%--<tr ng-repeat="dataVal in data | filter: {FilterByColumn : searchKeyword} | orderBy:predicate:reverse "> **Does not work--%>**
<%--<tr ng-repeat="dataVal in data | filter: {$ : searchKeyword} | orderBy:predicate:reverse "> **This works--%>**
<tr ng-repeat="dataVal in data | filter: GetFilter (FilterByColumn, searchKeyword) | orderBy:predicate:reverse "> **<!-- Does not work -->**
<td ng-repeat="hdr in headers | orderBy : hdr.displayOrder" ng-show="hdr.isVisible">
{{dataVal[hdr.name]}}
</td>
</tr>
</tbody>
</table>
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}} ; SearchBy = {{FilterByColumn}} ; Search Key : {{searchKeyword}} </pre>
</div>
This is the JS :
'use strict';
var MyApp = angular.module('MyApp', []);
MyApp.controller('MyGrid', function ($scope) {
$scope.predicate = 'Code';
$scope.reverse = false;
$scope.FilterByColumn = '$';
$scope.headers = [
{
"name": "Code",
"caption": "Code",
"isVisible": true,
"displayOrder": 12
},
{
"name": "DispName",
"caption": "My Name",
"isVisible": true,
"displayOrder": 1
},
{
"name": "Locked",
"caption": "Islocked",
"isVisible": true,
"displayOrder": 2
}
];
$scope.data =
[{
"Code": "1",
"DispName": "abdul",
"Locked": "0"
},
{
"Code": "2",
"DispName": "Hemant",
"Locked": "0"
},
{
"Code": "3",
"DispName": "Rahul",
"Locked": "0"
},
{
"Code": "4",
"DispName": "Sandy",
"Locked": "0"
},
{
"Code": "5 ",
"DispName": "Nihal",
"Locked": "0"
},
{
"Code": "6",
"DispName": "Sachin",
"Locked": "0"
},
{
"Code": "7",
"DispName": "abdul f",
"Locked": "0"
},
{
"Code": "8",
"DispName": "abdul g",
"Locked": "0"
},
{
"Code": "9",
"DispName": "abdul h ",
"Locked": "0"
},
{
"Code": "10",
"DispName": "abdul i",
"Locked": "0"
}
];
$scope.getValue = function (obj, PropName) {
return obj[PropName];
};
$scope.SetSort = function (objName) {
//alert(objName);
$scope.predicate = objName;
$scope.reverse = !$scope.reverse;
};
$scope.GetFilter = function (srchCol, Srchval) {
//alert(srchCol);
//alert(Srchval);
if (srchCol == "") {
return { $: Srchval };
}
else {
return { srchCol: Srchval };
}
};
});
That is because when you write { srchCol: Srchval } - srcCol is the property name and is not substituted with the value in variable srcCol, try this syntax instead:
$scope.GetFilter = function (srchCol, Srchval) {
if (srchCol == "") {
return { $: Srchval };
}
else {
filter = {};
filter[srchCol] = Srchval;
return filter;
}
};