Currently I am trying to save an updated function using angularJS. Till now i can edit the data, the data are can be updated on the database side, but its not showing in the frontend side. Unless i have to logout and login once again to view the updated result. Can i know how to fix this bug.
This is my controller.js code:
.controller('FilmDetailController', //havent done yet
[
'$scope',
'dataService',
'$routeParams',
'$location',
'$window',
'UserInfo',
function ($scope, dataService, $routeParams, $location,$window, UserInfo){
//var userName=dataService.getSessionService('user');
if(UserInfo.loggedIn){
$scope.film = [ ];
$scope.filmCount = 0;
var getFilmDetail = function (moviecode) {
dataService.getFilmDetail(moviecode).then(
function (response) {
$scope.film = response.data.ResultSet.Result;
//$scope.userLoginEmail = dataService.getSessionService('userEmail');
$scope.showSuccessMessage = true;
$scope.successMessage = "Film Success";
},
function (err){
$scope.status = 'Unable to load data ' + err;
}
); // end of getStudents().then
};
$scope.editedFilm = {};
$scope.save_note = function ($event,film) {
$scope.editedFilm = film;
dataService.saveNote($scope).then(
function (response) {
// getFilmDetail();
$window.location.href = '#/movieList';
//$window.location.reload();
console.log("done");
},
function (err){
$scope.status = 'Unable to load data ' + err;
}
);
// $scope.reloadRoute = function () {
// $location.path('/movieList');
// $window.location.reload()
// }//end of reload route fnction
}
// only if there has been a courseid passed in do we bother trying to get the students
if ($routeParams && $routeParams.filmid) {
// console.log($routeParams.filmid);
getFilmDetail($routeParams.filmid);
}
}else{
$location.path('/login');
}
}
]
);
Once i click on the save note button the note should be updated in both angular side and also the database side. Currently it can only be updated in the database side except the angular side. Thanks in advance for the help.
From what I can tell it looks like you need to store your note data in a service, and when the note has been successfully saved in your database, you need to push the new note into your service data.
I created a simple fiddle: https://jsfiddle.net/robrothedev/vgbqyv10/
function ItemService() {
var service = {
items: [],
addItem: addItem
};
return service;
function addItem(new_item) {
// run your http request and if the response is valid,
// push the new item to your service array
// $http.post(url,new_item).then(function(response) {
// service.items.push(response.data.new_item);
// });
}
}
function ItemsCtrl(ItemService) {
var vm = this;
vm.items = ItemService.items;
vm.new_item = {};
vm.addItem = addItem;
function addItem() {
ItemService.addItem(vm.new_item);
vm.new_item = {};
}
}
Related
In angularJS, With one call, when get the service response need access that json value in multiple controllers but in same page
I have two controller js file and both controllers are called in the same page when I called the service "this.getNavigationMenuDetails" in the first controller.js and as well as called in the controller2.js file as well. without timeout function, I want to access that same response which I get it from the "this.getNavigationMenuDetails" service in controller2.js. But it happened that service call twice in the page. I don't want to call the same service twice in a page.
When js are loading that time both controllers are called in the same layer then getting the response from the service so on the second controller2.js file code is not execute after the response. How can I solve this issue so that only one call i can get the response and access this response in controller2.js also.
controler1.js
var app = angular.module("navApp", []);
app.controller("navCtrl", ['$scope', 'topNavService', '$window', function ($scope, $timeout, topNavService, $window) {
$scope.menuItemInfo = {};
/*Navigation Menu new Code */
$scope.getNavigationDetails = function () {
topNavService.getNavigationMenuDetails().then(function (result) {
$scope.menuItemInfo = result;
angular.forEach($scope.menuItemInfo.items, function (val, key) {
if (val.menuTitle ===
$window.sessionStorage.getItem('selectedNavMenu')) {
if ($scope.menuItemInfo.items[key].isEnabled) {
$scope.menuItemInfo.items[key].isActive = 'highlighted';
} else {
$window.sessionStorage.removeItem('selectedNavMenu');
}
}
if (val.menuTitle === 'Find a Fair' && !val.hasSubMenu) {
$scope.menuItemInfo.items[key].redirectTo = appConfig.findafairpageurl;
}
});
});
};
$scope.init = function () {
if ($window.location.pathname.indexOf('all-my-fairs.html') > 0) {
if (angular.isDefined($cookies.get('cpt_bookfair'))) {
$cookies.remove('cpt_bookfair', {
path: '/'
});
}
}
$scope.getNavigationDetails();
$scope.callOnLoad();
};
$scope.init();
}]);
app.service('topNavService', ['$http', '$timeout', '$q'function ($http, $timeout, $q) {
var menuInfo;
this.getNavigationMenuDetails = function () {
if (!menuInfo) {
// If menu is undefined or null populate it from the backend
return $http.get("/etc/designs/scholastic/bookfairs/jcr:content/page/header-ipar/header/c-bar.getMenuDetails.html?id=" + Math.random()).then(function (response) {
menuInfo = response.data;
return menuInfo;
});
} else {
// Otherwise return the cached version
return $q.when(menuInfo);
}
}
}]);
Controller2.js
var app = angular.module('bookResourcePage', []);
app.controller('bookResourceCtrl', ['topNavService', '$scope', function (topNavService, $scope) {
$scope.topInfo = '';
topNavService.getNavigationMenuDetails.then(function success() {
$scope.productId = $scope.topInfo.isLoggedin;
$scope.linkParam = '?productId=' + $scope.productId;
}, function failure() {
console.error("something bad happened");
});
}]);
The service would work better if it cached the HTTP promise instead of the value:
app.service('topNavService', function ($http) {
var menuInfoPromise;
this.getNavigationMenuDetails = function () {
if (!menuInfoPromise) {
// If menu is undefined or null populate it from the backend
menuInfoPromise = $http.get(url);
};
return menuInfoPromise;
};
});
The erroneous approach of caching the value introduces a race condition. If the second controller calls before the data arrives from the server, a service sends a second XHR for the data.
You can do this with following approach.
Service.js
app.service('topNavService', function($http) {
var menuInfoPromise;
var observerList = [];
var inProgress = false;
this.addObserver(callback) {
if (callback) observerList.push(callback);
}
this.notifyObserver() {
observerList.forEach(callback) {
callback();
}
}
this.getNavigationMenuDetails = function() {
if (!menuInfoPromise && !inProgress) {
inProgress = true;
// If menu is undefined or null populate it from the backend
menuInfoPromise = $http.get(url);
this.notifyObserver();
};
return menuInfoPromise;
};
});
You have to make a function in service to add your controller's function on list. then each controller will register their get function on service and call service method to get data. first call will make service variable inProgress to true. so it will prevent for multiple server request. then when data available to service then it will call its notifyObserver function to message for all controller by calling their function.
Controller 1
app.controller('ctrl1', ['service', '$scope', function(service, $scope) {
service.addObserver('getData1'); //name of your controller function
$scope.getData1() {
service.getNavigationMenuDetails.then(function success() {
$scope.productId = $scope.topInfo.isLoggedin;
$scope.linkParam = '?productId=' + $scope.productId;
}, function failure() {
console.error("something bad happened");
});
}
$scope.getData1()
}]);
Controller 2
app.controller('ctrl1', ['service', '$scope', function(service, $scope) {
service.addObserver('getData2'); //name of your controller function
$scope.getData2() {
service.getNavigationMenuDetails.then(function success() {
$scope.productId = $scope.topInfo.isLoggedin;
$scope.linkParam = '?productId=' + $scope.productId;
}, function failure() {
console.error("something bad happened");
});
}
$scope.getData2()
}]);
with this approach you can real time update data to different controllers without have multiple same request to server.
i can't find a solution to this, basicly everytime i do a login, i want to store the user that i get from the node end point in the service, after that in my main Controller i should get the name of the user, but that never happen, dunno why
here is the code:
app.controller('MainCtrl', function ($scope, $state,$location,$http,user) {
$scope.user = {
nome: user.getProperty()
};
$scope.showRegister = function () {
$state.go('register');
}
$scope.showLogin = function () {
$state.go('login');
}
});
app.controller('loginController', function ($scope, $http, $state,user) {
$scope.login = function () {
var data = {};
data.password = $scope.loja.password;
data.email = $scope.loja.email;
$http.post('http://localhost:8080/login/',data)
.success(function (data) {
console.log(data);
user.setProperty(data.nome);
$state.go('home');
})
.error(function (statusText) {
console.log("failed");
});
}
});
user service
app.service('user', function () {
var property = {};
return {
getProperty: function () {
return property.nome;
},
setProperty: function (value) {
property.nome = value;
}
};
});
You could just watch your service for changes by adding this code to your MainCtrl:
$scope.$watch(function () { return user.getProperty();}, updateProp, true);
function updateProp(newValue, oldValue) {
$scope.user = {
nome: newValue
};
}
updateProp gets executed everytime the value of user.getProperty() changes.
Your main issue is with your MainCtrl . In the initial execution of MainCtrl there is no value set into your service so its get blank. MainCtrl executes before setting the value in the service.
$scope.user = {
nome: user.getProperty()
};
this code should be executed after setting the value in the service but it executes in the initialization of controller.
You can get the reference from the fiddle below.
http://jsfiddle.net/ADukg/9799/
I have a service to get (with array) all post from a server. I need to filter this array by id and show only this post in a single page.
In the service I have this code.
.service('PostAPI', function($http) {
this.getAll = function() {
return $http.get("ajax/getAllPosts.php");
}
this.getOne = function(data) {
return $http.get("ajax/searchPost.php?postID=" + data);
}
this.delete = function(data) {
if (confirm("Are you sure to delete this line?")) {
return $http.delete("ajax/deletePost.php?postID=" + data);
}
}
this.update = function(data) {
return $http.put("ajax/updatePost.php?postID" + data);
}
this.create = function() {
return $http.post("ajax/addPost.php");
}
})
In the controller
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
GetPost();
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).success(function(data) {
$scope.post = data;
console.log($scope.post);
});
};
In post HTML I have this.
<div>
<div>{{post.TASK}}</div>
<div>{{post.STATUS}}</div>
<b>Back</b>
</div>
I'm not able to get any data to show in the page, and also, i have no errors in my console. ¿Any idea?
Check your ajax/searchPost.php?postID= api that is this api returning single object or array, If this api returning object than it should work but If you getting array of single element in response of api then in your api success code use first element of array by data[0].
Controller code
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
GetPost();
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).success(function(data) {
$scope.post = data[0];
console.log($scope.post);
});
};
use then instaed of success. .then returns a promise so that you can handle the asynchrounous calls.
Also you are calling the getPost() method before function definition. So it may not get the promise.
call your getPost(), method after the function definition and check, so that it can receive the promise.
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).then(function(data) {
$scope.post = data[0];
console.log($scope.post);
});
};
GetPost();
I'm working on a Parse App with AngularJS, and reworking a controller to point to the logged in user when posting. On my database table, I've set a column "author" to point to the users. I made a separate service.js file which I call with Squeeg. When I click create, it does not input the data with the user.id. It works fine without it. How would I fix this to ensure that the user objectId is a part of the data is added to the database?
$scope.create=function(){
var user = Parse.User.current();
console.log(user.id);
Squeeg.create({ author:user.id, eventname:$scope.events.title, eventDescription:$scope.events.description}).success(function(data){
alert("done");
});
}
Since I need 50 reputation to comment, this needs to be asked here, have you accessed authfactory/authserverice to get the current user from there? Assuming you have login?
Then in authFactory you could have something like this.
app.factory('authFactory', ['$http', '$window', function ($http, $window) {
var authFactory = {};
authFactory.logIn = function (user) {
return $http.post('/login', user).success(function (data) {
authFactory.saveToken(data.token);
});
};
authFactory.saveToken = function (token) {
$window.localStorage['appToken'] = token;
};
authFactory.getToken = function () {
return $window.localStorage['appToken'];
};
authFactory.logOut = function () {
$window.localStorage.removeItem('appToken');
};
authFactory.currentUser = function () {
if(authFactory.isLoggedIn()){
var token = authFactory.getToken();
var payload = JSON.parse($window.atob(token.split('.')[1]));
return payload.username; // or return payload.id ..... / return payload
}
};
authFactory.isLoggedIn = function () {
var token = authFactory.getToken();
if(token){
var payload = JSON.parse($window.atob( token.split('.')[1]) );
return payload.exp > Date.now() / 1000;
} else {
return false;
}
};
return authFactory;
}]);
Then all you need to do is binding it with your controller to access it.
app.controller('AnyCtrl', ['$scope', 'authFactory',
function ($scope, authFactory) {
$scope.currentUser = authFactory.currentUser;
}
]);
I have the following controllers:
angular.module('app').controller('ParentCtrl', function(Service) {
var list = []
var init = function () {
Service.query().success(function() {
list = Service.getList();
});
}
});
angular.module('app').controller('ChildCtrl', function(Service) {
var list = []
var init = function () {
list = Service.getList();
}
});
angular.module('app').factory('Service', function($http) {
list = []
return {
query : function() {
$http.get('/path/to/my/api').success(function(data){
list = data
})
},
getList: function() {
return list;
}
}
});
My HTML is as follows:
<div ng-controller="ParentCtrl as parent">
<div ng-controller="ChildCtrl as child">
</div>
</div>
So basically when I receive the AJAX request I want both the controllers to get updated with the data
The best way would be to return the promise from $http.get:
angular.module('app').factory('Service', function($http) {
var promise;
return {
getList: function() {
if (promise) {
return promise;
}
promise = $http.get('/path/to/my/api');
return promise;
}
}
});
angular.module('app').controller('ParentCtrl', function(Service) {
var list = [];
var init = function () {
Service.getList().then(function(response) {
list = response.data;
});
}
});
angular.module('app').controller('ChildCtrl', function(Service) {
var list = [];
var init = function () {
Service.getList().then(function(response) {
list = response.data;
});
}
});
You can broadcast custom message to rootScope and Your controllers will get this message and handle it.
angular.module('app').controller('ParentCtrl', function($rootScope, $scope, Service) {
$scope.list = [];
$scope.$on('Service:list', function(event, data){
$scope.list = data;
});
});
angular.module('app').controller('ChildCtrl', function($rootScope, $scope, Service) {
$scope.list = [];
$scope.$on('Service:list', function(event, data){
$scope.list = data;
});
Service.query(); // run once, get in both controllers
});
angular.module('app').factory('Service', function($rootScope, $http) {
var list;
return {
query : function() {
$http.get('/path/to/my/api').success(function(data){
list = data;
$rootScope.$broadcast('Service:list', list);
})
},
getList: function() {
return list;
}
}
});
You could handle it in many ways. One simple way is to cache the promise and return it.
Example:-
angular.module('app').factory('Service', function($http, $q) {
var listPromise;
return {
getList: function() {
//If promise is already present then
return listPromise || (listPromise = $http.get('/path/to/my/api').then(function(response){
return response.data;
})
//Use the below 2 blocks (catch and finally) only if you need.
//Invalidate in case of error
.catch(function(error){
listPromise = null;
return $q.reject(error);
})
//Use finally to clean up promise only if you only need to avoid simultaneous request to the server and do not want to cache the data for ever.
.finally(function(){
listPromise = null;
}));
}
}
});
and in controller:
angular.module('app').controller('ParentCtrl', function(Service) {
var list = [];
var init = function () {
Service.getList().then(function(data) {
list = data;
});
}
});
angular.module('app').controller('ChildCtrl', function(Service) {
var list = [];
var init = function () {
Service.getList().then(function(data) {
list = data;
});
}
});
Caching a promise will make sure that it really does not matter who makes the first call and you always make the same service call to get the data and service will manage data caching via promise and prevent any duplicate calls.
Another practice is to implement a one-way data flow using flux pattern. Where you create stores that maintains data and it will make ajax call via a dispatcher and emits event to the subscribers of change event. There is an angular library (flux-angular) that can be used as well to implement this pattern. This will really help synchronize data between multiple components regardless of whether they are parent/child or siblings and regardless of who makes the first call etc..