How to set select options using firebase database and ng-repeat - angularjs

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

Related

Access userid into the directive from html

<div ng-repeat="user in children">
<a ng-click="swapUser(user.user_id);"></a>
<div ng-model="player.name" currentuser="user.user_id" inline-edit="parentUser.name" on-save="log('SAVE', value)" on-cancel="log('CANCEL', value)"></div>
</div>
Directive :
return {
scope: {
model: '=inlineEdit',
handleSave: '&onSave',
currentuser: '=',
handleCancel: '&onCancel'
},
link: function(scope, elm, attr) {
var currentuser = attr.currentuser;
console.log("Userid", attr.currentuser);
//Here I want to set the user_id so that i can update respective users
scope.save = function() {
var objInput = {};
objInput[field] = scope.model;
user.updateConfirmUser(objInput, currentuser)
.success(function () {
console.log("Saved");
});
}
Controller :
$scope.children = [
{
"name" : "Amy",
"age" : "50",
"height" : "5",
"type" : "2",
"user_id" : "1"
},{
"name" : "Rock",
"age" : "50",
"height" : "5",
"type" : "2",
"user_id" : "2"
},{
"name" : "Jimmy",
"age" : "50",
"height" : "5",
"type" : "3",
"user_id" : "3"
},{
"name" : "Michael",
"age" : "50",
"height" : "5",
"type" : "3",
"user_id" : "4"
}
];
How can i access the currentuser into my directive from html i setup current user to attr and trying to access into directive it says undefined user_id. Please take a look above code and suggest thanks
You are binding currentuser with value of "user.user_id" so only the user_id will be passed.
Try to pass the entire object: currentuser="user"

mongoDB - How to update/insert a field in an object which is within an array?

I have a method which inserts a new document into the collection "items".
//Example data of variables
var home = "home1";
var itemId = "123";
var username = Meteor.user().username;
//Upsert command
items.upsert({
'_id': home
}, {
$push: {
'createdItems': {itemId, username, home}
}
});
This creates a document like this:
"_id" : "home1",
"createdItems" : [
{
"itemId" : "123",
"username" : "Jon Doe",
"home" : "home1"
},
{
"itemId" : "456",
"username" : "Jon Doe2",
"home" : "home1"
},
{
"itemId" : "789",
"username" : "Jon Doe3",
"home" : "home1"
}
]
}
Now I need to be able to update the existing fields and insert new fields into these objects later. The itemId within these objects is the "reference". So I need a mongoDB function which inserts or updates fields by using the "itemId" as a query operator. Something like this:
//update a field
items.upsert({
'itemId': "123"
}, {
$set: {
'createdItems': {username: "Clark Kent"}
}
});
//insert new field
items.upsert({
'itemId': "123"
}, {
$set: {
'createdItems': {Value: 1000}
}
});
Or do I have to use $push? These commands are not delivering the results that I need. At the end the document should look like this:
"_id" : "home1",
"createdItems" : [
{
"itemId" : "123",
"username" : "Clark Kent",
"home" : "home1",
"Value" : 1000
},
{
"itemId" : "456",
"username" : "Jon Doe2",
"home" : "home1"
},
{
"itemId" : "789",
"username" : "Jon Doe3",
"home" : "home1"
}
]
}
Or do I have to use another data schema for the collection? If yes, which one can I choose when I want to have "itemId, "username" and "home" still in an array but "packed together"?
Many thanks.
If you want to update object in array query below will work fine
items.update({
'createdItems.itemId': '123'
}, {
$set: {
'createdItems.$.username': 'Clark Kent'
}
})
You can also easily add new fields to the object using the same query.
items.update({
'createdItems.itemId': '123'
}, {
$set: {
'createdItems.$.username': 'Clark Kent'
'createdItems.$.newField': 'newFieldValue'
}
})

Angular filters: search two categories of many

I've been trying to think of a way to search products by Name AND Producer, not just one of them. Looking through documentation, I found how to tie search filter to one kind, but not multiple (not all).
For example, if I have a list of persons with names, surnames and phone numbers, I'd like to be able to search through only name and surname in one input field. If I type in my search field, this model will look for a match in Name and Producer. How do I achieve this?
Thank you in advance!
My code above.
HTML:
<div>
<label>Search</label>
<input ng-model="query" type="text" placeholder="Search for name or producer" autofocus>
<label>
</div>
<table>
<tr>
<td>Name</td>
<td>Producer</td>
<td></td>
<td>Type</td>
<td>Packaging</td>
<td>Is it alcoholic?</td>
<td>Volume</td>
<td>Popularity</td>
<td>Country</td>
<td>Added</td>
<td>Price</td>
</tr>
<tr ng-repeat="item in products | filter:query | orderBy: drinkOrder:direction">
<td>{{item.name}}</td>
<td>{{item.producer}}</td>
<td><img ng-src="img/{{item.picture}}.jpg" alt="{{item.name}}" height="50px"></td>
<td>{{item.type}}</td>
<td>{{item.packaging}}</td>
<td>{{item.alko}}</td>
<td>{{item.volume}}</td>
<td>{{item.popularity}}</td>
<td>{{item.country}}</td>
<td>{{item.added}}</td>
<td>{{item.price}}</td>
</tr>
</table>
JS file app.js:
var myApp = angular.module('myApp', []);
myApp.controller('MyController', ['$scope', '$http', function ($scope, $http) {
$http.get('/lynda/ithouse/js/data.json').success(function(data) {
$scope.products = data;
$scope.drinkOrder = 'popularity';
});
}]);
JSON file:
[
{
"name" : "Sample Beer",
"producer" : "Great Beer Producer",
"picture" : "two",
"type" : "beer",
"packaging" : "glass",
"alko" : "yes",
"volume" : "1",
"popularity" : "1",
"country" : "Latvia",
"added" : "2015-01-03",
"price" : "20,40"
},{
"name" : "Sample Cider",
"producer" : "Great Cider Producer",
"picture" : "one",
"type" : "cider",
"packaging" : "plastic",
"alko" : "yes",
"volume" : "2",
"popularity" : "3",
"country" : "Estonia",
"added" : "2015-01-03",
"price" : "20,40"
},{
"name" : "Best Wine",
"producer" : "Wine for You",
"picture" : "eight",
"type" : "wine",
"packaging" : "glass",
"alko" : "yes",
"volume" : "2",
"popularity" : "5",
"country" : "Lithuania",
"added" : "2015-01-03",
"price" : "20,40"
},{
"name" : "Another Beer",
"producer" : "Beer Land",
"picture" : "seven",
"type" : "beer",
"packaging" : "aluminium",
"alko" : "no",
"volume" : "4",
"popularity" : "2",
"country" : "Latvia",
"added" : "2015-05-03",
"price" : "21,40"
}
]
You can create your own custom filter like below
Filter
.filter('customFilter', function() {
return function(query) {
var out = [];
angular.forEach($scope.products, function(value, key) {
if (value['name'] == query || value['producer'] == query)
this.out.push(value)
})
return out;
}
});
Fiddle Here

AngularFire & ngOptions

I am struggling to populate a select form element. Here is the syntax that I have so far. It will not grab the program.title and populate the ngOptions.
<select ng-model="student.program" ng-options="program.title for program in programList.title">
<option value="">Select A Program</option>
</select>
Here is the basic JSON structure of my data on Firebase:
{
"-JNIBeRDAuNN9c7SGZ91" : {
"location" : "Online",
"director" : "Shawn Clark",
"title" : "Web Design & Development"
},
"-JNIBuaQlWyEyWRjONPa" : {
"location" : "Online",
"director" : "Walen Morrow",
"title" : "Graphic Design"
},
"-JNIBmIwasMYOPRPupHl" : {
"location" : "Campus",
"director" : "Tracy Monohan",
"title" : "Web Design & Development"
},
"-JNKGPNj-lGzqHJ92RTD" : {
"location" : "Online",
"director" : "Glen Speedy",
"title" : "Theory of Animation & Physics"
},
"-JNK9oTO97PfSo-0wQfY" : {
"location" : "Campus",
"director" : "John Myers",
"title" : "Instructional Design & Technology"
},
"-JNIC3Tldo-Qi3ru2ph7" : {
"location" : "Campus",
"director" : "George Narrow",
"title" : "Graphic Design"
},
"-JNK8cdgdHKjH2meKl9x" : {
"location" : "Online",
"director" : "Stacy McNally",
"title" : "Instructional Design & Technology"
}
}
I believe you are looking for
<select ng-model="student.program" ng-options="program.title for (id, program) in programList"><option value="">Select A Program</option></select>
Your JSON's root object is an object, not an array. See angular documentation for object data sources
See Plunker
Try the following code.
It should work:
<select ng-model="student.program" ng-options="program.title for program in programList"><option value="">Select A Program</option></select>
Thanks

Dynamic form with parent child combos

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();
};
}
}
});

Resources