It works when the first bind occurs,I want the list rebind data when a select input(id is 'checkin') changes,what should I do?
var m = angular.module('users', []);
m.controller('UserList', function($scope) {
$scope.getdata = function() {
var u = "http://www.example.com/admin?queryusers";
var userlist = this;
var body = {
activityid: "10",
checkin: $('#checkin').val()
};
$.ajax({
url: u,
type: "post",
async: false,
data: body,
success: function(data) {
userlist.users = data;
}
});
return userlist.users;
};
this.users=$scope.getdata();
$('#checkin').change(function() {
this.users=$scope.getdata();
$scope.$apply();
});
});
Your Problem is you are using jQuery in angularjs that is missing with
angular digest cycle thats why binding is not updating on html.
You shouldn't use $.ajax inside angular, that will messed up with angular digest cycle, you need to use $http call that will do ajax call safely, & update the binding after ajax gets completed.
Also you shouldn't use jquery event on element inside angular, you have to replace that change event to use ng-change then there will not need to worry about digest cycle.
Markup
<input type="checkbox" id="checkin" ng-model="myCheckbox" ng-change="getdata()"/>
Controller
var m = angular.module('users', []);
m.controller('UserList', function($scope, $http) {
$scope.getdata = function() {
var u = "http://www.example.com/admin?queryusers";
var userlist = this;
var body = {
activityid: "10",
checkin: $('#checkin').val()
};
$http({
url: u,
method: "post",
//async: false,
data: body,
}).success(function(data) {
userlist.users = data;
});
};
this.users = $scope.getdata();
//below code will call getdata directly from html on ng-change
//$('#checkin').change(function() {
// this.users = $scope.getdata();
// $scope.$apply();
//});
});
Related
I'm using &http in angular js to make REST calls. And when I make a new call, I want to dismiss the previous call. So I wrap the data call in the service and call the service in the controller. And I'm using the global parameter to save the last call object. So whenever I call the function getsth(), it will replace the lastcall with the new one. But when I debug, it did replace the lastcall with new one, but the previous then still triggers. One solution is the cancel the previous call and I tried it works. But my question is can I overwrite the $http object so that I don't have to handle it. Thanks
Controller:
var lastCall;
$scope.getsth = function(){
lastcall = service.datacall();
lastcall.then()
}
Service:
service.datacall = function(){
var promises = [];
promises.push($http({url:method...}).then(function))
return $q.all(promises);
}
This blogpost explains your use-case pretty well:
http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx
app.factory("movies", function($http, $q){
var getById = function(id){
var canceller = $q.defer();
var cancel = function(reason){
canceller.resolve(reason);
};
var promise =
$http.get("/api/movies/slow/" + id, { timeout: canceller.promise})
.then(function(response){
return response.data;
});
return {
promise: promise,
cancel: cancel
};
};
return {
getById: getById
};
});
app.controller("mainController", function($scope, movies) {
$scope.movies = [];
$scope.requests = [];
$scope.id = 1;
$scope.start = function(){
var request = movies.getById($scope.id++);
$scope.requests.push(request);
request.promise.then(function(movie){
$scope.movies.push(movie);
clearRequest(request);
}, function(reason){
console.log(reason);
});
};
$scope.cancel = function(request){
request.cancel("User cancelled");
clearRequest(request);
};
var clearRequest = function(request){
$scope.requests.splice($scope.requests.indexOf(request), 1);
};
});
I am trying to add angular-typeahead to my app for search suggestion taking help from this Plunkr.
This is the code of app.js file:
var myApp = angular.module('myApp', ['ngRoute','siyfion.sfTypeahead']);
myApp.factory('websitesSvc',function($http, $log, $q) {
return {
getwebsites: function(){
//Create a promise using promise library
var deferred = $q.defer();
$http({method: 'GET', url: '/api/websites/'}).
success(function(data, status, headers,config){
deferred.resolve(data);
}).
error(function(data, status, headers,config){
deferred.reject(status);
});
return deferred.promise;
}
};
});
myApp.controller('MyCtrl', ['$scope','websitesSvc',
function($scope,websitesSvc) {
$scope.searchString=null;
websitesSvc.getwebsites().then(function(websites){
$scope.websites = websites;
console.log($scope.websites); //It works here
});
//Output undefined
//THIS IS NOT WORKING
console.log($scope.websites);
var websites = new Bloodhound({
datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.domain_name); },
queryTokenizer: Bloodhound.tokenizers.whitespace,
//want to pass the websites array list from service to local
local:websites, //THIS IS NOT WORKING
});
// initialize the bloodhound suggestion engine
websites.initialize();
$scope.numbersDataset = {
displayKey: 'domain_name',
source: websites.ttAdapter()
};
// Typeahead options object
$scope.exampleOptions = {
highlight: true
};
}
]);
The thing is the I am not able to pass the value of $scope.websites to the typeahead.How to make get the value of websites from services so that I can pass the resultant array to the typeahead?
After editing the code as suggested by red 6 hours ago Kalhano Toress Pamuditha, I am able to access the data.But now I am getting this
websitesSvc.getwebsites().then(function(websites){
$scope.websites = websites;
console.log($scope.websites); //It works here
});
//Output undefined
//THIS IS NOT WORKING
console.log($scope.websites); this will execute before websitesSvc.getwebsites() completes,
javascript code is not hold until sync calls to be complete it will execute the rest of the code, that is the case where u get the undefined.
you will get the data after websitesSvc.getwebsites() promise. so if u need to execute something after this data received, you can execute a function inside then like below
websitesSvc.getwebsites().then(function(websites){
$scope.websites = websites;
console.log($scope.websites); //It works here
$scope.methodAfterComplete();
});
$scope.methodAfterComplete = function() {
// this will call after completing the websitesSvc.getwebsites()
}
so you can place your code inside methodAfterComplete method which require $scope.websites data. for example ;
$scope.methodAfterComplete = function() {
var websites = new Bloodhound({
datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.domain_name); },
queryTokenizer: Bloodhound.tokenizers.whitespace,
local:websites,
});
// initialize the bloodhound suggestion engine
websites.initialize();
$scope.numbersDataset = {
displayKey: 'domain_name',
source: websites.ttAdapter()
};
// Typeahead options object
$scope.exampleOptions = {
highlight: true
};
}
Hi I have two controllers
pqsAppModule.controller('NotificationBoxController',function($scope,items) {
$scope.list = items.list();
})
and
pqsAppModule.controller('NotificationController',function($scope,items) {
$scope.list = items.list();
})
I need to create an "items" service that would do an ajax request and return data for any controller which would have it injected. And I want, that the query will be done only once, and items will be shared between all controllers.
pqsAppModule.factory('items', function($http) {
var items = [];
var itemsService = {};
$http.get('api/notification').then(function(response){
items = response.data;
});
itemsService.list = function() {
return items;
};
return itemsService;
});
But I don't understand why angular makes the request, and receives data, but all items in controllers are empty.
It happens because the factory should be defined by different way.
(I took dummy URL only to load data by async way)
HTML
<div ng-controller="NotificationBoxController">
<button ng-click="showMe();">press me</button>
<pre>NotificationBoxController: {{items.getList()|json}}</pre>
</div>
<div ng-controller="NotificationController">
<pre>NotificationController: {{items.getList()|json}}</pre>
</div>
JS
var pqsAppModule = angular.module('myApp', []);
pqsAppModule.controller('NotificationBoxController',function($scope,items) {
$scope.items = items;
$scope.showMe= function(){
items.query();
}
});
pqsAppModule.controller('NotificationController',function($scope,items) {
$scope.items = items;
});
pqsAppModule.factory('items', function ($http) {
var current = {};
var address = 'Singapore, SG, Singapore, 153 Bukit Batok Street 1';
var URL = 'http://maps.googleapis.com/maps/api/geocode/json?address=' + address + '&sensor=true';
var factory = {
query: function () {
var data = $http({method: 'GET', url:URL}).then(function (result) {
current = result.data.results[0];
}, function (result) {
alert("Error: No data returned");
});
},
getList: function () {
return current;
}
}
return factory;
});
Demo Fiddle
From this example we call items.getList() from HTML for both controllers. But if we want to update the model through the controller, we need a listener like $watch
Try this
$http.get('api/notification').then(function(response){
angular.foreach(response.data,function(item) {
items.push(item);
});
});
Basically do not create a new array but fill the existing one.
I am new to angular js. I am trying to call factory service method 'getScoreData' from ng-change of select, but not able to get it done. please help.
Html code:
<select ng-model="Score" ng-change="getScoreData(Score)" ng-options="c.name for c in Scores"></select>
Angularjs code:
var app = angular.module('audiapp', []);
app.controller('audiLayoutCtrl', function ($scope, ScoreDataService) {
ScoreDataService.getScoreData($scope.Score, function (data) {
$scope.ScoreData = data;
});
});
app.factory('ScoreDataService', function ($http) {
return {
getScoreData: function (Score, callback) {
var params = {
questionCode: Score.code
}
return $http({
url: 'Home/GetAvgData',
method: 'GET',
params: params
}).success(callback);
}
};
});
above is the service factory method and its instantiate from controller. I tried instantiating from ng-change of select but its neither giving error nor its getting called.
You have at least two issues in your code:
ng-change="getScoreData(Score)
Angular doesn't see getScoreData method that refers to defined service
getScoreData: function (Score, callback)
We don't need to use callback since GET returns promise. Use then instead.
Here is a working example (I used random address only for simulation):
HTML
<select ng-model="score"
ng-change="getScoreData(score)"
ng-options="score as score.name for score in scores"></select>
<pre>{{ScoreData|json}}</pre>
JS
var fessmodule = angular.module('myModule', ['ngResource']);
fessmodule.controller('fessCntrl', function($scope, ScoreDataService) {
$scope.scores = [{
name: 'Bukit Batok Street 1',
URL: 'http://maps.googleapis.com/maps/api/geocode/json?address=Singapore, SG, Singapore, 153 Bukit Batok Street 1&sensor=true'
}, {
name: 'London 8',
URL: 'http://maps.googleapis.com/maps/api/geocode/json?address=Singapore, SG, Singapore, London 8&sensor=true'
}];
$scope.getScoreData = function(score) {
ScoreDataService.getScoreData(score).then(function(result) {
$scope.ScoreData = result;
}, function(result) {
alert("Error: No data returned");
});
};
});
fessmodule.$inject = ['$scope', 'ScoreDataService'];
fessmodule.factory('ScoreDataService', ['$http', '$q', function($http) {
var factory = {
getScoreData: function(score) {
console.log(score);
var data = $http({
method: 'GET',
url: score.URL
});
return data;
}
}
return factory;
}]);
Demo Fiddle
The factory sends data to the server and its processed correctly but after that the ".then" in the controller is not being called below.
Kindly let me know why the "then" part is not being executed in the controller here after the successful ajax call.
factory
myapp.factory('startCampFactory',function($http,$q,$rootScope){
return {
startNewCampaign : function(){
var e = $("input#email");
var email = e.val();
var campname = $("input#campaignname").val();
var about = $("textarea#about").val();
var tamt = $("input#targetamount").val();
var edate = $("input#enddate").val();
var invitees = $("input#invitees").val();
var file_data = $("#file").prop("files")[0];
var form_data = new FormData();
form_data.append("file",file_data);
form_data.append("email",email);
form_data.append("campaignname",campname);
form_data.append("about",about);
form_data.append("targetamount",tamt);
form_data.append("enddate",edate);
form_data.append("invitees",invitees);
console.log(email+about+campname);
var deferred = $q.defer();
$.ajax({
type:'POST',
url: "http://localhost:8080/startcampaign",
data:form_data,
contentType:false,
processData:false,
cache:false,
dataType:"json",
success:function(msg,status)
{
//if(status=="success")
deferred.resolve("success");
$rootScope.$apply();
},
error:function()
{
deferred.reject();
$rootScope.$apply();
}
});
return deferred.promise;
}
}
});
conrtoller
function startCampCtrl($scope,startCampFactory)
{
$scope.startcamp = function(){
$("#submit").prop('disabled',true);
startCampFactory.startNewCampaign().then(function(d){
alert("here");
var temp = "<div class=\"alert alert-dismissable alert-success\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button> <strong>Campaign Saved successfully</strong></div>";
$(temp).prependTo("#startcamp");
$("#submit").prop('disabled',false);
$("input#campaignname").val('');
$("textarea#about").val('');
$("input#targetamount").val('');
$("input#enddate").val('');
$("input#invitees").val('');
$("input#file").val('');
},
function(){//On error
var temp = "<div class=\"alert alert-dismissable alert-warning\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button> <strong>Campaign could not be saved, please try again</strong></div>";
$(temp).prependTo("#startcamp");
$("#submit").prop('disabled',false);
});
}
}
You're using $.ajax() to trigger the call. The correct way to do it is to use the $http service. When a call is made through that service an $apply is automatically trigerred , and all your promises will get executed in that $apply cycle.
If you want to trigger the promises from your success function inside the $.ajax() call,
I suppose you can do it inside an $apply cycle:
.....
success:function(msg,status){
$rootScope.$apply( function() {
deferred.resolve("success");
});
}
....
Here is the working fiddle with correct way to invoke promise