AngularJS Factory and Parse.com User Authentication - angularjs

I am playing around with AngularJS using Parse.com as it's backend and am having an issue when I try go authenticate and deuthenticate with Parse. I am abe to do both these functions, but my views don't update.
app.factory('hsUser', ['$http', function($http){
var dataObject = null;
return {
get: function()
{
var tmpData = Parse.User.current();
console.log(tmpData);
if(tmpData && dataObject == null)
{
dataObject = {};
keys = Object.keys(tmpData);
keys.forEach(function(value)
{
dataObject[value] = tmpData[value];
});
console.log(dataObject);
}
return dataObject;
},
authenticate: function(username, password)
{
console.log('auth');
Parse.User.logIn(username, password, {
success: function(userData) {
dataObject = {};
keys = Object.keys(userData);
keys.forEach(function(value)
{
dataObject[value] = userData[value];
});
},
error: function(userData, errorData) {
console.log(errorData);
}
});
},
deauthenticate: function()
{
Parse.User.logOut();
dataObject = Parse.User.current();
},
doRegister: function(registration)
{
console.log(registration);
return {
success: true
}
}
}
}]);
Here are my controllers.
app.controller('HeaderController', ['hsConfig','hsUser', function( hsConfig, hsUser)
{
this.config = hsConfig.get();
this.user = hsUser.get();
}]);
app.controller('AuthController', ['hsUser', function( hsUser)
{
this.user = hsUser.get();
this.authUser = {
emailAddress: "testinguser",
password: "testinguser",
remember: false,
}
this.authenticate = function()
{
hsUser.authenticate(this.authUser.emailAddress, this.authUser.password);
}
this.deauthenticate = function()
{
this.user = hsUser.deauthenticate();
console.log('Deauthenticated')
}
}]);
Here is the HTML for the directive that creates the navbar
<div class="header" ng-controller="HeaderController as headCtrl">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">{{ headCtrl.config.brand }}</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right" ng-hide="headCtrl.user">
<li class="dropdown" ng-controller="AuthController as authCtrl">
<a class="dropdown-toggle" href data-toggle="dropdown">
Sign In
<strong class="caret"></strong>
</a>
<div class="dropdown-menu auth-form-container" style="padding: 15px; padding-bottom: 0px;" >
<form role="form" ng-submit="authCtrl.authenticate();">
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" placeholder="Enter email" ng-model="authCtrl.authUser.emailAddress" >
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" placeholder="Password" ng-model="authCtrl.authUser.password">
</div>
<div class="form-group checkbox">
<label>
<input type="checkbox" ng-model="authCtrl.authUser.remember"> Remember Me
</label>
</div>
<div class="form-group">
<button class="btn btn-primary btn-full">Sign In</button>
</div>
</form>
</div>
</li>
<li class="divider-vertical"></li>
<li>Register</li>
</ul>
<ul class="nav navbar-nav navbar-right" ng-show="headCtrl.user">
<li>Profile</li>
<li class="divider-vertical"></li>
<li ng-controller="AuthController as authCtrl">
<a href ng-click="authCtrl.deauthenticate();">Sign Out</a>
</li>
</ul>
</div>
</div>
</nav>
</div>
The entire project including Parse keys can be found here. I'll delete the keys once I figure out wtf my problem is.
https://github.com/thenetimp/hackerspace
If anyone can point me into what I am doing wrong and explain it so I can understand what I need to do with other Models I would greatly appreciate it.

whenever you update the model outside of angulars context, I.e in the callback of a promise, you need to use $scope.apply to notify angular.

Related

AngularJS GitHub API| Conributors list in the repository list

I have a problem with the repository list in the list of all Conributors for this repository.
I want to create a Contributors list in the list of repositories downloaded using GitHub Api. However, I can not get these data for each repository and put them in html.
Has anyone any idea how to do this?
Thank you in advance for your help
My code:
App in html
<div ng-controller="gitApi" ng-app="app">
<div class="container">
<h1 class="text-center">
<span ng-hide="userData" />Loading</span>
<span />{{userData.name}}</span>
<br>
<a href="{{userData.html_url}}" class="btn btn-default">
{{userData.login}}
</a>
</h1>
<div class="panel panel-default">
<div class="panel-heading">
<form class="form-inline">
<span>
<h4>Repos <span class="badge">{{repoData.length}}</span>
<input ng-model="searchText" placeholder="Search" class="form-control input-sm">
</h4>
</span>
</form>
</div>
<div class="panel-body">
<div class="list-group">
<div ng-repeat="orgs in orgsData | filter:searchText | orderBy:predicate:reverse" class="list-group-item ">
<div class="row">
<div class="col-md-6">
<h4>
<a href="{{repo.html_url}}" target="_blank">
{{orgs.name}}
</a>
<small>{{orgs.description}}</small>
</h4>
<small>
<a href="{{orgs.homepage}}" class="">
<i class="fa fa-link"></i> WebPage
</a>
</small>
</div>
<div class="col-md-6">
Conributors List:
<div ng-repeat=" | filter:searchText | orderBy:predicate:reverse" class="list-group-item ">
<div class="row">
<div class="col-md-12">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
APP.js
angular.module('app', [])
.controller('gitApi', ['$scope', '$http', function($scope, $http) {
$scope.reposLoaded = false;
$scope.userLoaded = false;
$scope.orgsLoaded = false;
$http.get("https://api.github.com/users/angular")
.success(function(data) {
$scope.userData = data;
loadOrgsRepos();
});
var loadOrgsRepos = function() {
$http.get("https://api.github.com/orgs/angular/repos")
.success(function(data) {
$scope.orgsData = data;
});
}
$scope.predicate = '-updated_at';
}]);
You can get all contributors url from contributors_url and make an API call for each one of these, storing the result in the original $scope.orgsData array :
"use strict";
var githubApp = angular.module('app', []);
githubApp.controller('gitApi', ['$scope', '$http', '$q', function($scope, $http, $q) {
$http.get("https://api.github.com/users/angular")
.success(function(data) {
$scope.userData = data;
loadOrgsRepos();
});
var loadOrgsRepos = function() {
$http.get("https://api.github.com/orgs/angular/repos")
.success(function(data) {
$scope.orgsData = data;
var contribs = [];
for (var i in data) {
contribs.push(data[i].contributors_url);
}
$q.all(contribs.map(function(item) {
return $http({
method: 'GET',
url: item
});
}))
.then(function(results) {
results.forEach(function(val, i) {
$scope.orgsData[i].contributors = val.data;
});
});
});
}
$scope.repo_sort = '-updated_at';
$scope.contrib_sort = '-contributions'
}]);
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body id="page-top" class="index">
<div ng-controller="gitApi" ng-app="app">
<div class="container">
<h1 class="text-center">
<span ng-hide="userData">Loading</span>
<span>{{userData.name}}</span>
<br>
<a href="{{userData.html_url}}" class="btn btn-default">
{{userData.login}}
</a>
</h1>
<div class="panel panel-default">
<div class="panel-heading">
<form class="form-inline">
<span>
<h4>Repos <span class="badge">{{repoData.length}}</span>
<input ng-model="searchText" placeholder="Search" class="form-control input-sm">
</h4>
</span>
</form>
</div>
<div class="panel-body">
<div class="list-group">
<div ng-repeat="orgs in orgsData | filter:searchText | orderBy:repo_sort:reverse" class="list-group-item ">
<div class="row">
<div class="col-md-8">
<h4>
<a href="{{repo.html_url}}" target="_blank">
{{orgs.name}}
</a>
<small>{{orgs.description}}</small>
</h4>
<small>
<a href="{{orgs.homepage}}" class="">
<i class="fa fa-link"></i> WebPage
</a>
</small>
</div>
<div class="col-md-6">
Conributors List:
<div class="list-group-item">
<div class="row">
<div class="col-md-4">
name
</div>
<div class="col-md-4">
avatar
</div>
<div class="col-md-4">
contributions
</div>
</div>
</div>
<div ng-repeat="contrib in orgs.contributors | filter:searchText | orderBy:contrib_sort:reverse" class="list-group-item">
<div class="row">
<div class="col-md-4">
<a href="{{contrib.html_url}}" target="_blank">
{{contrib.login}}
</a>
</div>
<div class="col-md-4">
<img ng-src="{{contrib.avatar_url}}" height="42" width="42" />
</div>
<div class="col-md-4">
<p>
{{contrib.contributions}}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
Here is another fiddle

How to use controller as syntax in the following scenario

controller as syntax problem
I am a newbie to angular, so please forgive me if i'm wrong. I have a problem where a service is used for certain operation. In this case, adding books to cart.
I have followed the recommended way using controller as syntax instead of $scope. But in kart-list.html, i'm not able to access kart details, since this operation is done by BookListCtrl.
app.js
var app = angular.module("app", ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/books", {
templateUrl: "partials/book-list.html",
controller: "BookListCtrl",
controllerAs: 'booklist'
})
.when("/kart", {
templateUrl: "partials/kart-list.html",
controller: "KartListCtrl",
})
.otherwise({
redirectTo: "/books"
});
});
app.factory("kartService", function() {
var kart = [];
return {
getKart: function() {
return kart;
},
addToKart: function(book) {
kart.push(book);
},
buy: function(book) {
alert("Thanks for buying: ", book.name);
}
};
});
app.factory("bookService", function() {
var books = ['some data'];
return {
getBooks: function() {
return books;
},
addToKart: function(book) {
}
}
});
app.controller("KartListCtrl", function(kartService) {
var self = this;
self.kart = kartService.getKart();
self.buy = function(book) {
kartService.buy(book);
};
});
app.controller("HeaderCtrl", function() {
var self = this;
self.appDetails = {};
self.appDetails.title = "BooKart";
self.appDetails.tagline = "We have collection of 1 Million books";
});
app.controller("BookListCtrl", function(bookService, kartService) {
var self = this;
self.books = bookService.getBooks();
self.addToKart = function(book) {
kartService.addToKart(book);
};
});
book-list.html
<div id="bookListWrapper">
<form role="form">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search here..." />
</div>
</form>
<ul class="list-unstyled">
<li class="book" ng-repeat="book in booklist.books" style="background: white url('imgs/{{book.imgUrl}}') no-repeat">
<div class="book-details clearfix">
<h3>{{book.name}}</h3>
<p>{{book.price}}</p>
<ul class="list-unstyled list-inline">
<li>Rating: {{book.rating}}</li>
<li>Binding: {{book.binding}}</li>
<li>Publisher: {{book.publisher}}</li>
<li>Released: {{book.releaseDate}}</li>
</ul>
<p>{{book.details}}</p>
<button class="btn btn-info pull-right" ng-click="addToKart(book)">Add to Kart</button>
</div>
</li>
</ul>
</div>
kart-view.html
<div id="bookListWrapper">
<p>Please click on buy button to buy the book.</p>
<ul class="list-unstyled">
<li class="book" ng-repeat="book in kart" style="background: white url('imgs/{{book.imgUrl}}') no-repeat">
<div class="book-details clearfix">
<h3>{{book.name}}</h3>
<p>{{book.price}}</p>
<ul class="list-unstyled list-inline">
<li>Rating: {{book.rating}}</li>
<li>Binding: {{book.binding}}</li>
<li>Publisher: {{book.publisher}}</li>
<li>Released: {{book.releaseDate}}</li>
</ul>
<p>{{book.details}}</p>
<button class="btn btn-info pull-right" ng-click="buy(book)">Buy</button>
</div>
</li>
</ul>
</div>
Problem is how use controller as syntax for kart-list.html near ng-repeat to access kart details?
Your'e using the controller as feature but you haven't covered all view references.
book-list.html
<button ... ng-click="addToKart(book)">Add to Kart</button>
Change to
<button ... ng-click="booklist.addToKart(book)">Add to Kart</button>
kart-view.html
<li ... ng-repeat="book in kart" ...
...
<button ... ng-click="buy(book)">Buy</button>
Change to
<li ... ng-repeat="book in KartListCtrl.kart" ...
...
<button ... ng-click="KartListCtrl.buy(book)">Buy</button>
You have to prefix booklist while calling addToKart() method in book-list.html.
Use below file which will resolve your issue:
book-list.html
<div id="bookListWrapper">
<form role="form">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search here..." />
</div>
</form>
<ul class="list-unstyled">
<li class="book" ng-repeat="book in booklist.books" style="background: white url('imgs/{{book.imgUrl}}') no-repeat">
<div class="book-details clearfix">
<h3>{{book.name}}</h3>
<p>{{book.price}}</p>
<ul class="list-unstyled list-inline">
<li>Rating: {{book.rating}}</li>
<li>Binding: {{book.binding}}</li>
<li>Publisher: {{book.publisher}}</li>
<li>Released: {{book.releaseDate}}</li>
</ul>
<p>{{book.details}}</p>
<button class="btn btn-info pull-right" ng-click="booklist.addToKart(book)">Add to Kart</button>
</div>
</li>
</ul>
</div>

Invoke function inside a controller from Fancybox2

I have this directive
app.directive('fancybox', function($compile, $timeout){
return {
link: function($scope, element, attrs){
$(element).fancybox({
'transitionIn': 'elastic',
'transitionOut': 'elastic',
'width': '250',
'height': '250',
'speedIn': 600,
'speedOut': 200,
'overlayShow': false,
afterLoad: function () {
$timeout(function(){
$compile($("#content-popup"))($scope);
$scope.$apply();
$.fancybox.resize();
})
this.title = $(this.element).next('.content-popup-footer').html();
},
helpers: {
title: {
type: 'inside'
}
},
});
}
}
});
I'm trying to invoke a function that is inside the controller that invoked the fancybox. This is the html that i'm sending to the fancybox
<a href="{{content.source}}" fancybox="fancybox" id="content-popup"
class="transparent-box content-popup content-picture-container"
rel="campaign-picture-popup" "><a/>
<!--Fancybox footer data begin-->
<div class="content-popup-footer" style="display:none">
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="content-popup-user-info">
<img class="content_picture_profile_pic"
ng-src="{{content.photographer.instagramProfilePicture}}"/>
<div class="content_popup_user_name">
{{content.photographer.instagramUserName}}
</div>
<i class="fa fa-circle small-dot"></i>
<span id="instagram-picture-time-taken">{{content.timeTaken}}</span>
</div>
</div>
<div class="col-md-6 col-sm-6 content_popup_link_container">
<div class="content_popup_link">
<i class="fa fa-link"></i>
View source
</div>
</div>
</div>
<div class="row" id="content-popup-picture-info-row">
<div class="col-md-12">
<p>{{content.description}}</p>
</div>
<div class="col-md-12" id="content-popup-statistics">
<span><i class="fa fa-thumbs-o-up"></i>{{content.likesCount}}</span>
<span><i class="fa fa-comment-o"></i>{{content.commentsCount}}</span>
</div>
</div>
<form role="form">
<div class="form-body">
<div class="form-group">
<div class="input-icon">
<i class="fa fa-pencil-square-o"></i>
<input id="name" type="text" class="form-control"
placeholder="Add caption">
</div>
</div>
</div>
</form>
<div>
<button class="btn select-content-btn"
ng-click="onSelectedContent(content)"
ng-style="content.selected && {'background-color':'#2ecc71'} || !content.selected && {'background-color':'#95a5a6'}">
<i class="fa fa-check" ng-if="content.selected"></i>
<span ng-if="!content.selected">Select</span>
<span ng-if="content.selected">Selected</span>
</button>
</div>
</div>
</div>
<!--Fancybox footer data end-->
The problem that the scope doesn't being recognized inside the fancybox window and i can't invoke the onSelectedContent().
How can i add the scope to the fancybox window so i could activate all the scope's functions and props?

Add to cart using angular js

I want to create the shopping cart using angular js.And i am new to angular js.My question is how to use cart functionality As of now i displayed the products list using REST API
<div class="col-sm-2" ng-repeat="product in productdata">
<div class="col-item">
<div class="photo">
<a ng-href="#/productdesc">
<img src="{{product.imageUrl}}" class="img-responsive" alt="a" />
</a>
</div>
<div class="info">
<div class="row">
<div class="col-md-12">
<h5>{{product.productname}}-{{product.id}}</h5>
<h5 class="price-text-color">${{product.price}}</h5>
</div>
</div>
<div class="separator clear-left">
<p class="btn-add">
<input type="number" value="1" class="form-control text-center" min="1">
</p>
<p class="btn-details">
<a href="#" class="hidden-sm btn btn-group-sm btn-primary">
<i class="fa fa-shopping-cart"></i>Add
</a>
</p>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
And i need to know how the values will be saved as cookies or session in browser.
You could use localStorage or sessionStorage to save you shppping cart data.
For example you could use a package like angular-local-storage for working with sessionStorage in a AngularJS app.
UPDATE:
Disclaimer: I didn't tested this code! Is only a sample code to show you the way that you could follow. Good luck! :)
In your app config:
myApp.config(function (localStorageServiceProvider) {
localStorageServiceProvider
.setPrefix('yourAppName');
localStorageServiceProvider
.setStorageType('sessionStorage');
});
Service:
myApp.factory('CartProduct', function(localStorageService) {
var cartProducts = [];
function init() {
if (localStorageService.get('cart-products').length) {
cartProducts = localStorageService.get('cart-products');
}
}
init();
function getAll() {
return cartProducts;
}
function add(product) {
cartProducts.push(product);
localStorageService.set('cart-products', cartProducts);
}
return {
add: add,
getAll: getAll
};
});
Controller:
myApp.controller('MyCtrl', function($scope, CartProduct) {
$scope.addToCart = function (product) {
CartProduct.add(product);
}
});
HTML:
<div class="separator clear-left">
<p class="btn-add">
<input type="number" ng-model="product.quantity" value="1" class="form-control text-center" min="1">
</p>
<p class="btn-details">
<a href="#" ng-click="addTocart(product)" class="hidden-sm btn btn-group-sm btn-primary">
<i class="fa fa-shopping-cart"></i>Add
</a>
</p>
</div>

Scope variables don't reflect in template

I have part of an angular app setup as follows:
<section >
<div ng-controller="setHeaderCtrl" class="navbar navbar-default header">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#collapsed-bar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand brand-text" ui-sref="index">
<span class="sports-text">Sports</span>
<span class="gully-text">Gully</span>
</a>
</div>
<div class="collapse navbar-collapse" id="collapsed-bar">
<ul class="nav navbar-nav navbar-left" ng-if="searchingAway">
<li class="local-search-cont">
<input type="text" class="local-type-top" placeholder="Search">
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-if="!userObject">
<a ng-click="showLogin()" class="navbar-txt-block" style="cursor: pointer;">
Login
</a>
</li>
<li ng-if="userObject.user">
<a class="navbar-txt-block" ui-sref="home" style="cursor: pointer;">
Home
</a>
</li>
<li ng-if="userObject">
{{userObject}}
<a class="navbar-txt-block" style="cursor: pointer;">
{{userDetails.first_name}} {{userDetails.last_name}}
</a>
</li>
</ul>
</div>
</div>
</div>
</section>
and my setHeaderCtrl is as follows:
app.controller('setHeaderCtrl',['$scope', '$rootScope', '$http', '$state', 'Page', '$modal',
function($scope, $rootScope, $http, $state, Page, $modal){
$rootScope.$on('userSet', function(){
var authKey = $rootScope.authKey;
$http.defaults.headers.common.Authorization = 'Token '+authKey;
$http.get('/loginCheck/').success(function(data){
$scope.userObject = data;
$scope.userDetails = data.user;
});
});
$scope.userObject = {}
$http.get('/loginCheck/').success(function(data){
$scope.userObject.user = data;
$scope.userDetails = data.user;
console.log($scope.userDetails);
}).error(function(data, status){
if(status == 401){
$scope.userObject.user = undefined;
}
});
$rootScope.$on('setAwayHeader', function(){
$scope.searchingAway = true;
});
$rootScope.$on('setIndexHeader', function(){
$scope.searchingAway = false;
});
$scope.showLogin = function(){
$modal.open({
windowClass: 'modal fade login-modal',
templateUrl: '/static/partials/modals/loginModal.html',
controller: 'loginCtrl'
})
}
}
])
My problem is such that the {{userObject}} or {{userDetails}} never displays. I can guarantee that there's a response from the server because console.log shows the correct data.
The expression ng-if="userObject" is not good, it always true. Replace it by boolean, or by userObject property: ng-if="userObject.user". Jsfiddle

Resources