How to match item from two different databases based using angularjs - angularjs

I need a bit of guidance figuring out how to make two similar values in angular js from two different tables. The tables am using are a user table and a school table. So what I need to do is based on the logged in user I am supposed to get a school name related to that user but currently am not sure how to go about this. Any assistance in guiding me on how to go about this would be greatly appreciated.
School Service Controller Code:
angular.module('starter').factory('Schools',['apiUrl','$resource', 'UserInfo', function(apiUrl,$resource, UserInfo){
var factory = $resource(apiUrl + '/schools/:schoolId',
{
schoolId: '#_id'
}, {
update: {
method: 'GET'
}
});
return factory;
}]);
Profile Controller Code Snippet:
angular.module('starter.controllers')
.controller('ProfileController', function($scope,$http,$state,Schools, $ionicPopup, apiUrl, UserInfo,$ionicLoading,$ionicHistory,Users,Authentication) {
$scope.apiUrl = apiUrl;
$scope.authentication = Authentication;
$scope.state = $state;
$scope.selected = {};
var user = Authentication.user.school;
$scope.find = function(queryParams){
$scope.place = [];
var user = $scope.authentication.user.school;
var school = Schools.query({_id: user.school})
var params = queryParams || {};
params._id = user;
Schools.query(params, function(response){
if (params._id === school){
// response.splice(0, $scope.place.lengh);
// for(var x = 0; x< response.lengh; x++){
// $scope.place.push(response[x]);
// }
$scope.place = response[0].name;
}
else{
$scope.place = response;
}
})
}
$scope.signOut = function(){
$ionicPopup.confirm({
title: "SIGN OUT",
template: '<p align="center">' + 'PLEASE CONFIRM IF YOU WANT TO SIGN OUT'+ '</p>',
buttons: [
{ text: "NO",
type: 'button button-outline button-assertive',
onTap:function(e){
return false;
}
},
{
text: "YES",
type:'button-positive',
onTap:function(e){
//now you can clear history or goto another state if you need
$ionicHistory.clearHistory();
$ionicHistory.nextViewOptions({ disableBack: true, historyRoot: true });
$state.go('signin');
return true;
}
}
]
});
};
});
My value for "$scope.find function" is returned properly but is the whole list of school names and details rather than the one which matches the user.

I think this is server side logic. When you pass logged in user to your api then do some database query based on that user in the server side and return json object with all the list of schools .

I finally figured a way to get the correct values based on the id reference of school in the user table. I had to use the angularjs forEach method to first query the data then filter it in a if statement to get the results I was looking for.
Solution:
$scope.find = function(){
var school = $scope.authentication.user.school;
$scope.schoolName = Schools.query(function(results) {
results.forEach(function(result) {
if (result._id === school) {
$scope.schoolName = result.name;
return $scope.schoolName;
}
});
});
}

Related

AngularJs Check if user role matchs state role for authentication

I'm building an authentication system and I've done almost everything. I'm stuck in the authorization based on user role. If I use numbers, like user.role > 1, pass, if not, return false, I can make it work properly.
But I'm planning to move to an array based role, so I can create 'modules' and make a better control.
Auth process
It all starts with a return from the database, if the user/pass is ok, the DB will return a json array containing user name, id and roles, like this:
{
id: 1,
name: 'John Doe',
role: ['user', 'order', 'service']
}
In my $state, i have it defined like this:
.state('home', {
[...code...]
data: {
requireLogin: true,
role: ['user']
}
})
.state('sales', {
[...code...]
data: {
requireLogin: true,
role: ['sales', 'admin']
}
})
.state('order', {
[...code...]
data: {
requireLogin: true,
role: ['order', 'admin']
}
})
So for example, that user should be able to access the state 'order' and 'home', because at least one of the roles is in the .state data role. But I'm having trouble validating it inside my factory. I kind of made it, but sometimes it returns some other unxpected numbers, or at least i don't know the proper validation.
This is my factory:
//token = user data returned from data base;
//type = user role from state;
var _getTipo = function(token, type) {
var authUser = token.indexOf(type);
return authUser;
};
Sometimes i get the return -1, 10 or 2..
What i did wrong? Or whats the proper way to check if at least one of the user roles is in the state role?
Whenever I do user authentication I use a directive as an attribute like this:
app.directive('permissions', function (currentUser) {
return {
restrict: 'A',
priority: 100000,
scope: false,
link: function (scope, element, attr) {
var accessDenied = true;
var attribute = attr.permissions;
if (currentUser.role.indexOf(attribute) !== -1) {
accessDenied = false;
}
if (accessDenied) {
element.children().remove();
element.remove();
}
}
};
});
You would then call it like this:
<div permissions="user">
//info
</div>
You would just need to pass the currentUser object to the directive. Or you could just change your factory:
var _getTipo = function(token, type) {
var authenticated = false
for(var i = 0;i < token.role.length;i++){
var userRole = token.role[i];
for(var x = 0;x < type.length;x++){
var stateRole = type[x];
if (userRole == stateRole) {
authenticated = true;
}
}
}
return authenticated;
};
To turn this string: "['user', 'sales']" into an array:
JAVASCRIPT
var string = "['user', 'sales']";
var array = string.replace('"[',"").replace(']"',"").split("', '");
PHP
$string = "['user', 'sales']";
$string = str_replace('"[',"",$string);
$string = str_replace(']"',"",$string);
$array = explode("', '",$string);

Linking user's contacts in firebase with md-contacts-chips

I am having difficulty getting my head around on how I could link my users contacts in Firebase with md-contacts-chips from https://material.angularjs.org/0.11.2/#/demo/material.components.chips
Basically, each registered user can add people they know via email to their contacts list. The users firebase structure is as follows:
firebase
-$uid1
contacts
$uid2 - userObject
$uid3 - userObject
-$uid2
contacts
$uid1 - userObject
$uid3 - userObject
-$uid3
contacts
$uid1 - userObject
$uid2 - userObject
etc..
Is it possible to ng-repeat a users contacts as an array of objects?
How should I configure the md-contacts-chip?
The example has a function called loadContacts() which has the contacts set.
How would I be able to set my user objects as contacts? The return object is contact and I would like to find a way for it to return the queried object.
function loadContacts() {
var contacts = [
'Marina Augustine',
'Oddr Sarno',
'Nick Giannopoulos',
'Narayana Garner',
'Anita Gros',
'Megan Smith',
'Tsvetko Metzger',
'Hector Simek',
'Some-guy withalongalastaname'
];
return contacts.map(function (c, index) {
var cParts = c.split(' ');
var contact = {
name: c,
email: cParts[0][0].toLowerCase() + '.' + cParts[1].toLowerCase() + '#example.com',
image: 'http://lorempixel.com/50/50/people?' + index
};
contact._lowername = contact.name.toLowerCase();
return contact;
});
}
Thanks
I'm by no means an expert, just a trial and error fanatic. That being said I did get this to work. I the issues is that "md-contact-chip" uses "push and splice" to adjust the array, and as firebase states that's a bad idea. If we had access to replace push with $add() or splice with $remove() this should work properly.
I was looking at the custom chips setup and it seems possible because you can call a function during the chip's add and remove, then with a custom chip template could maybe get the same look as the contact-chips.
Anyway here is what I did to get it working with md-contact-chips. Also I've adjusted this one to work with a list of items, not contacts, cause I wanted the picture for the items.
The key to it should be get your whole person obj, then set the ng-model="ctrl.person.contacts" inside the controller make sure to have an array created if person.contacts does not exist. "ctrl.person.contacts = ctrl.person.contacts || [];
Yes your are not properly updating the firebase object but you when you run
ctrl.person.$save() you are just completely updating the db.
Html
<div layout="column" ng-cloak>
<div>
<p>Items selected</p>
<pre>{{ctrl.item.installedItems}}</pre>
</div>
<input type="button" ng-click="ctrl.updateInstalledItems()" value='update'>
<md-content class="md-padding autocomplete" layout="column">
<md-contact-chips
ng-model="ctrl.item.installedItems"
md-contacts="ctrl.querySearch($query)"
md-contact-name="alseSn"
md-contact-image="image"
md-require-match="true"
md-highlight-flags="i"
filter-selected="ctrl.filterSelected"
placeholder="Select installed items">
</md-contact-chips>
</md-content>
</div>
Controller
app.controller('ItemChipCtrl', ['items', 'item', '$q', '$log',
function (items, item, $q, $log) {
var ctrl = this;
ctrl.items = items;
ctrl.item = item;
ctrl.item.installedItems = ctrl.item.installedItems || [];
ctrl.querySearch = querySearch;
ctrl.allItems = loadItems(ctrl.items);
ctrl.filterSelected = true;
ctrl.updateInstalledItems = function() {
$log.info('Update....')
$log.log(ctrl.installedItems);
ctrl.item.$save();
}
/**
* Search for contacts.
*/
function querySearch (query) {
var results = query ?
ctrl.allItems.filter(createFilterFor(query)) : [];
return results;
}
/**
* Create filter function for a query string
*/
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(item) {
return (item.alseSn.indexOf(lowercaseQuery) != -1);
};
}
function loadItems(items) {
/*var items = $scope.items */
return items.map(function (c, index) {
var item = {
alseSn: c.alseSn || c,
alseCard: c.alseCard,
installedOn: c.installedOn || null,
image: 'img/items/47/'+c.alseCard+'.jpg' || null
};
return item;
});
}
}
]);
route injections
.when('/settings/:alseSn', {
templateUrl: 'settings.html',
controller: 'ItemChipCtrl as ctrl',
resolve: {
auth: function($location, Auth){
return Auth.$requireAuth().then(function(auth) {
return auth;
},function(error){
$location.path('/login');
});
},
item: function($route, Items, Auth){
return Auth.$requireAuth().then(function(){
return Items.getItem($route.current.params.alseSn).$loaded();
});
},
items: function(Items, Auth){
return Auth.$requireAuth().then(function(){
return Items.all.$loaded();
});
}
}
})

Getting the phoneNumber using $cordovaContacts

I'm trying to get all the contacts in the phone using ng-cordova, I success to do that like the following, I create a service in AngularJS:
.factory("ContactManager", function($cordovaContacts) {
return {
getContacts: function() {
var options = {};
options.filter = "";
options.multiple = true;
//get the phone contacts
return $cordovaContacts.find(options);
}
}
})
Also the method find in the ng-cordova is't like the following:
find: function (options) {
var q = $q.defer();
var fields = options.fields || ['id', 'displayName'];
delete options.fields;
navigator.contacts.find(fields, function (results) {
q.resolve(results);
},
function (err) {
q.reject(err);
},
options);
return q.promise;
}
And did the following inside the controller:
ContactManager.getContacts().then(function(result){
$scope.users= result;
}, function(error){
console.log(error);
});
I noticed that in the $scope.users I find the formatted, middleName ..., but I can't find the phoneNumber, how can I get also the phoneNumbers?
If you log the contacts you should see an object with a phoneNumbers array in it.
ContactManager.getContacts().then(function(result){
$scope.users= result;
console.log(result);
...
If you don't it's something else.
I also made a somewhat close mock json of what the return looks like.

AngularJS service storing and updating data

I have a simple app that shows a list of people each with a link to an edit controller. The edit controller gets the person by id. Once the edit form has been submitted, the page is redirected back to the person list.
I have a method to update the service data in the callback after the server saves the person. The method I use does in fact work, however, I wasn't sure if there was a better way to achieve this. After much searching I haven't found a concrete answer so I wanted to reach out to the AngularJS community here for help.
Here is a fiddle: http://jsfiddle.net/7bGEG/
var app = angular.module('peopleApp',[]);
app.controller('ListCtrl',function($scope,People) {
People.getList().then(function(response) {
$scope.list = response; // show list of people with a link to new route to edit
});
});
app.controller('EditCtrl',function($scope,$location,$routeParams,People) {
// edit route so get person by id
People.getById($routeParams.id).then(function(response) {
$scope.person = response.person;
});
// submit save person form and send back to person list
$scope.savePerson = function() {
People.savePerson($scope.person).then(function(response) {
$location.path('/');
});
}
});
app.factory('People',function($http,$q) {
var people = [];
var people_q = $q.defer();
$http.get(url).then(function(response) {
people = response.data;
people_q.resolve(people);
});
return {
getList: function() {
return people_q.promise;
},
getById: function(id) {
return $http.get(url).then(function(response) {
return response.data;
});
},
savePerson: function(person) {
return $http.post(url).then(function(response) {
// find person in person array and remove them
for (i=0; i < people.length; i++) {
if (people[i].person_id == person.person_id) {
people.splice(i,1);
break;
}
}
// add new person data
people.push(response.data);
return response.data;
});
}
}
});

How do I do custom model data parsing in backbone.js?

While using backbone to hit an api, I've found that I need to only include some of the data in the response. The webserver is giving me back metadata in addition to data concerning my objects that I don't need.
The following solution works, but doesn't feel right. Is there a standard way of doing this?
var accountsCollection = new AccountsCollection();
accountsCollection.fetch({success : function(collection){
var results = new AccountsCollection();
collection.each(function(item){
results.add(new AccountModel({
id: item.toJSON().result[0].id,
messageText: item.toJSON().messageText,
address1: item.toJSON().result[0].address1,
address2: item.toJSON().result[0].address2
}));
});
onDataHandler(results);
}});
EDIT: This was my final solution based on the accepted answer:
parse: function(response) {
var accounts = [];
_.each(response['result'], function (account) {
accounts.push(account);
});
return accounts;
}
You could try overriding the Backbone.Collection.parse method and do some crazy underscore stuff. No idea if it fits your data..
var keysILike = ['foo', 'bar'];
AccountsCollection.extend({
parse: function(response) {
return _.compact(_.flatten(_.map(response, function (model) {
var tmp = {};
_.each(_.keys(model), function (key) {
if (_.contains(keysILike, key)) tmp[key] = model[key];
})
return tmp;
})));
}
});
With respect to #Sushanth's awesomeness you definitely want to use this solution:
var keysILike = ['foo', 'bar'];
AccountsCollection.extend({
parse: function(response) {
_.each(response, function (model) {
_.each(_.keys(model), function (key) {
if (!_.contains(keysILike, key)) delete model[key]
})
});
return response;
}
});

Resources