Update facebook page list in to a drop down list - angularjs

I am working on an angular app which integrates with facebook. I have given the code below,
$scope.getCompanyPages = function () {
fb.login(function (response) {
fb.api('/me/accounts', function (apiresponse) {
if (typeof apiresponse !== 'undefined' && typeof apiresponse.data !== 'undefined') {
$scope.facebookPages = apiresponse.data;
$scope.facebookPages.push({ id: "", name: 'Please select a page' });
$scope.selectedItem = $scope.facebookPages[2];
console.log($scope.facebookPages);
}
});
}, { scope: 'manage_pages' });
};
HTML
<div class="row">
<div class="col-xs-12 col-sm-6 center">
<a href="#" ng-click="shareToMyWall()">
<div class="primary-task">
<i class="fa fa-user fa-3x">
</i>
<h2 class="heading-text fa-bold">Personal Wall</h2>
</div>
</a>
</div>
<div class="col-xs-12 col-sm-6 center">
<a href="#" ng-click="getCompanyPages()">
<div class="primary-task">
<i class="fa fa-building fa-3x">
</i>
<h2 class="heading-text fa-bold">Company Wall</h2>
</div>
</a>
<select ng-if="facebookPages.length > 0" ng-change="shareToFacebookPage(selectedItem.id)" ng-model="selectedItem" ng-options="item.name for item in facebookPages track by item.id"></select>
</div>
</div>
The above method is called in hyperlink click (ng-click) event and the when the response comes back the drop down should update with data. The data does come back but it doesn't update straight away, rather I have to do another click anywhere in the page to update drop down list.

The data in the model is updated when you do the first ng-click. However, AngualrJS probably does not do check so the view still shows the old data. You can force a $digest() check and tell AngualrJS to compare old data and new data and update it if there is any difference. You can use $timeout, $evalAsync, or $apply to trigger $digest() which will update the data immediately.
For example:
$timeout(function () {
$scope.getCompanyPages = function () {...}
//or
$scope.facebookPages = apiresponse.data;
})
Edit: according to Angular JS best coding practice
Always wrap 3rd party API call-backs in to $apply to notify AngularJS
regarding out of environment changes.

Related

Angular. Why filter invokes automatically?

I'm new in angular and I reeding A.Freeman's book "Pro Angular JS".
So I stuck in one of examples trying to understand why filter in ng-repeat is triggered.
Here is the code:
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
</div>
<div class="panel panel-default row" ng-controller="productListCtrl">
<div class="col-xs-3">
<a ng-click="selectCategory()" class="btn btn-block btn-default btn-lg">Home</a>
<a ng-repeat="item in data.products | orderBy:'category' | unique:'category'" ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg">
{{item}}
</a>
</div>
<div class="col-xs-8">
<div class="well" ng-repeat="item in data.products | filter:categoryFilterFn">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">
{{item.price | currency}}
</span>
</h3>
<span class="lead">{{item.description}}</span>
</div>
</div>
</div>
</body>
and
angular.module("sportsStore")
.controller("productListCtrl", function ($scope, $filter) {
var selectedCategory = null;
$scope.selectCategory = function (newCategory) {
selectedCategory = newCategory;
}
$scope.categoryFilterFn = function (product) {
return selectedCategory == null ||
product.category == selectedCategory;
}
});
categoryFilterFn is one that confuses me. Why it's invoking when I press catefory buttons (with selectCategory() method on ng-click) since I never call categoryFilterFn explicitly?
Answering you question - because of $digest. You don't have call categoryFilterFn directly. Your selectedCategory has changed which is used in categoryFilterFn and categoryFilterFn is bound to scope.
Not sure how I can describe it correctly but here my explanation.
There are two "independent" parts :
The repeat iterate over an array of items.
If you select an category via ng-click function you set the new category in the scope.
Here kicks the filter function in, witch ties it up.
It is triggered because a new category is selected ($digest) and "reordering" the array (like map function in plain Javascript) and the angular magic (ng-repeat) displays only items with this category.
And that's the reason why I love angular so much 🤓

AngularJS: Empty value when access in view

I'm newbie in AngularJS, I have a question, please explain to me the reason of my mistake. At first, I have a factory name CategoryParent with this function declared like this,
routerApp.factory('CategoryParent', function($http) {
var categoryParentFactory = {};
var hostCMSAPI="http://***.***.***.***:****";
// get all categories
categoryParentFactory.allCategoryParents = function() {
console.log("call get allCategoryParents");
return $http.get(hostCMSAPI+'/api/categoryparents/');
};
.......
and a controller call this function named categoryParentController:
.controller('categoryParentController', function(CategoryParent,$scope) {
console.log("cateParent ctrl");
$scope.processing=true;
$scope.dataList=[];
$scope.getAllCategoryParents=function(){
CategoryParent.allCategoryParents().success(function(response){
$scope.processing = false;
$scope.list=response;
});
I'm using ui.router like this (nested view):
.state('home.cateParentMenu',{
url:'/cateParentMenu',
templateUrl:'categoryParentTop.html',
controller:'categoryParentController',
controllerAs:'categoryParent'
})
Parent view trigger controller function here:
The Homey Page
This page demonstrates nested views.
<a ui-sref=".list" class="btn btn-primary">List</a>
<a ui-sref=".paragraph" class="btn btn-danger">Paragraph</a>
<a ui-sref=".cateParentMenu" class="btn btn-warning" ng-click="getAllCategoryParents()">cateParentMenu</a>
and last, the children view come here
data show
{{processing}}
{{list}}
{{item.cate_parent_name}}
<ul class="nav navbar-nav" >
data show
{{processing}}
{{list}}
<li data-ng-repeat="item in list.data"><a ui-sref=".detail({cate_parent_id:item.cate_parent_id})" ng-click="getById(item.cate_parent_id)" ui-sref-active="active" id="{{item.cate_parent_id}}">{{item.cate_parent_name}}</a></li>
</ul>
<div class="col-sm-6">
<div ui-view=""></div>
<!--<div ui-view="serviceRef"></div>-->
<!--<div ui-view="categoryRef"></div>-->
</div>
I set $scope.list and $scope.processing to transfer result to view. But in view I show {{list}}, nothing appears and {{processing}} = true ???
Why? please help me, many thanks to all your suggests.
Controller
Fix $scope.dataList=[]; to $scope.list=[];

Data can not be synchronized using angularjs

I store a data in a factory like this:
module.factory('AddedStockListData', function(){
var list= [];
var size = 0;
return{
getList: function(){
return list;
},
setList: function(data){
list = data;
},
getSize:function(){
return size;
},
setSize:function(){
size++;
},
setDelSize:function(){
size--;
}
}
});
And in my controller the code as follows:
$scope.stocksSearchList = AddedStockListData.getList();
$scope.load = function($done){
$timeout(function() {
document.getElementById("showTipsToDropDown").style.display = "none";
$scope.stocksSearchList = AddedStockListData.getList();
$done();
}, 500);
}
My html like this:
<ons-page ng-controller="createPortStockController">
<ons-pull-hook ng-action="load($done)" var="loader" id="pullDown">
<span ng-switch="loader.getCurrentState()">
<span ng-switch-when="initial"><ons-icon size="35px" icon="ion-arrow-down-a"></ons-icon> Pull down to refresh</span>
<span ng-switch-when="preaction"><ons-icon size="35px" icon="ion-arrow-up-a"></ons-icon> Release to refresh</span>
<span ng-switch-when="action"><ons-icon size="35px" spin="true" icon="ion-load-d"></ons-icon> Loading data...</span>
</span>
</ons-pull-hook>
<div>
<ons-toolbar class="DCF" fixed-style>
<div class="left">
<ons-back-button style="color:white;"></ons-back-button>
</div>
<div class="center" style="font-size:22px;" >Create Portfolio</div>
<div ng-click="create()"class="right" style="font-size:18px;color:white;margin-top:10px;padding-right:10px;" >Create</div>
</ons-toolbar>
<div class="addStockButton" ng-click = "myNavigator.pushPage('portStockSearchList.html', { animation : 'slide'})">
<i class="fa fa-plus" ></i>Add Stock
<p id="showTipsToDropDown"style="margin:0px;font-size:12px;text-align:center;color:#adadad;">After your first time add stocks, please drop down to refresh</p>
</div>
<div class="stockSearchList">
<div ng-repeat="stockSearch in stocksSearchList">
<div class="stockSearchOne">
<div class="stockSearchOneComp">{{stockSearch.company}}</div>
<div class="stockSearchOneInfo">Symbol: {{stockSearch.symbol}} | Exchange:{{stockSearch.exchange}} </div>
</div>
</div>
</div>
</div>
Actually, I change the factory data in next page,I want to make this page change the display while the factory data is changed.
But the result is , at the first time I change the data in the next page and back to this page, the data will not display, and I will refresh this page by use the ons-pull-hook> and then if I go to the next page to change the data, when I back to here, data will be synchronized display .
So the result is at the first time , I have to refresh the page to get the data, but after the first time, I don't need to do this
Anybody can help me to solve this problem?
Try using $scope.$apply() after the data have been fetched, it should update the content without any need to refresh the page. You can learn more about $scope.$apply() here.

PUT request in Angular not sending updated data within XHR Header

I am a beginner and new to AngularJS. I am trying to build an Edit/Update function.
The edit function doesn't do much, it just copies the model data to the Form inputs:
// Edit post
$scope.editPost = function(post){
$scope.title = post.title;
$scope.link = post.link;
};
The Update function should (after clicking the Update Button) take the edited data of the inputs, to update the post model:
// Update post
$scope.updatePost = function(post){
posts.update(post, {
title: $scope.title,
link: $scope.link
}).success(function() {
ToastService.show('Post updated');
});
};
The Edit Part works, when I edit the title input and click the Submit Button of the Edit Form, it sends a PUT request, but it seems to doesn't send the updated data within the PUT - it just sends a request with the original data.
The posts.js service:
angular.module('bidrp')
.factory('posts', [
'$http',
function($http){
var o = {
posts: [{title:"hey", upvotes:123}]
};
o.update = function(post) {
return $http.put('/posts/' + post.id, post).success(function(data){
o.posts.push(data);
});
};
Template where Post is displayed and editPost is triggered:
<div ng-repeat="post in posts | orderBy: '-upvotes'">
<md-button class="md-icon-button md-accent" aria-label="Vote-Up" ng-click="incrementUpvotes(post)">
<i class="material-icons">thumb_up</i>
</md-button>
{{post.upvotes}}
<span style="font-size:20px; margin-left:10px;">
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</span>
<span>
posted by <a ng-href="#/users/{{post.user.username}}">{{post.user.username}}</a>
</span>
<span>
Comments
Edit
Delete
</span><br>
<div ng-show="showEditForm" ng-include="'home/_edit-post.html'"></div>
</div>
<div ng-include="'home/_add-post.html'"></div>
_edit-post.html partial:
<form ng-submit="updatePost(post)">
<h3>Edit post</h3>
<div ng-include="'home/_form-post.html'"></div>
</form>
_form-post.html partial:
<md-input-container>
<label>Title</label>
<input required type="text" ng-model="title">
</md-input-container>
<md-input-container>
<label>Link</label>
<input type="text" ng-model="link">
</md-input-container>
<md-button type="submit" class="md-raised md-primary">Submit</md-button>
What am I doing wrong, how can I send the edited form data within the PUT request?
This is happening because, your, are just passing the original post object generated by ngRepeat to the update function not the $scope.post. When using ng-model="post" this will be attached to the $scope object.
You do not need the editPost function, the new data are already passed to $scope.title/$scope.title by ngModel directive (doing this will re-update the $scope.tile, $scope.link with the old values):
// Edit post
$scope.editPost = function(post){
$scope.title = post.title;
$scope.link = post.link;
};

AngularJs how to reload a template page after selecting a charater

I am using http.get and i need to reload a template after selecting a character so that my template gives the answer according to what I selected
The code of the template
<div class="container-fluid" ng-controller="CriterioCtrl">
<div id="result"></div>
<div>
Selected Items:
<div ng-repeat="id in selection">
{{id}}
</div>
</div>
<div ng-repeat-start="crit in data" class="row">
<h2 align="center">{{crit.name}}</h2>
<div ng-repeat="caracter in crit.characters" class="col-md-4">
<div type="checkbox" value="{{caracter.id}}" ng-checked="selection.indexOf(caracter.id) > -1" ng-click="clickSelection(caracter.id)">
<a href="#crit" class="thumbnail" ng-click="clickCriterios(caracter.id)">
<h4 align="center">{{caracter.name}}</h4>
<img ng-src="http://skaphandrus.com/{{caracter.image_url}}"/>
</a>
</div>
</div>
</div>
<div ng-repeat-end>
</div>
<!--<button class="btn" ng-click="toggle()">Toggle</button>
<p ng-show="visible">Hello World!</p> codigo de um botao -->
</div>
This code is for the selection
$scope.selection=[];
$scope.clickSelection = function clickSelection(caracterId) {
var idx = $scope.selection.indexOf(caracterId);
// is currently selected
if (idx > -1) {
$scope.selection.splice(idx, 1);
}
// is newly selected
else {
$scope.selection.push(caracterId);
}
var selectedId = $scope.selection;
console.log(selectedId);
// Check browser support
if (typeof(Storage) != "undefined") {
// Store
localStorage.setItem("idSelect", selectedId);
// Retrieve
document.getElementById("result").innerHTML = localStorage.getItem("idSelect");
}
};
This code is the http part in another controller
MyApp.controller('EspeciesCtrl', function ($scope, $http) {
$http({
url: 'someurl',
method: "post",
params: {module_id: localStorage.getItem("idMod"),"characters[]": [localStorage.getItem("idSelect")]}
})
.then(function(res){
$scope.data = res.data;
});
});
This is the code of the template that have to change after the selection
<div class="container-fluid" ng-controller="EspeciesCtrl">
<div class="row">
<div ng-repeat="esp in data" class="col-md-6">
<a href="#infEsp" class="thumbnail" ng-click="clickEspecie(esp.id)">
<h4 align="center">{{esp.name}}</h4>
<img ng-src="{{esp.image_src}}"/>
</a>
</div>
</div>
</div>
How can i do that?
edit 1
If I've correctly understood, you may need to use ng-show (https://docs.angularjs.org/api/ng/directive/ngShow) whose boolean value checks if the user selected anything and show the extra bit of code you need, instead of trying to have another http request.
Also, it seems like you are using $scope.data for both the esp and the crit, so you will end up with the errors.
You probably don't need to reload the template.
You may want to use the data in $scope.data inside the template in order to let Angular manage the update on the view. As soon as the $scope.data changes, the rendered HTML changes too.
I can't comment but it would be helpful if you could share the template you are using and be more specific in your request :)

Resources