I am newbie for angularjs.I have list of persons and each person have edit and delete button. when i click to edit button ng-dialog box was open and show person details and person can change and save information on database,behind save button ajax call trigger and update information on database.
Updating information on database work well but on UI side my view doesn't reflect my database changes.
I had tried to apply "$scope.$apply();" method but i got error message "$digest already in progress".
Please help me,how can refresh my scope after ajax call.
You can use shared service for that and broadcast any event through this service. Broadcasted event can be listened in any controller with $scope.$on.
For example:
angular.module("app", []).factory("sharedService", function($rootScope){
var mySharedService = {};
mySharedService.values = {};
mySharedService.personWasUpdated = function(){
$rootScope.$broadcast('update');
}
return mySharedService;
});
Ctrl for person editing.
app.controller('personEditController', ['$scope', 'sharedService', '$http', function ($scope, sharedService, $http) {
$scope.updatePerson = function(newPerson){
$http.post("../some URL/..", {person: newPerson})
.success(function(data){
sharedService.personWasUpdated(); //event broadcasing
})
};
}
Ctrl for displaying list of persons.
app.controller('personController', ['$scope', 'sharedService', '$http', function ($scope, sharedService, $http) {
var loadPersonsData = function(){
$http.get("../some URL/..").
.success(function(data){
$scope.persons = data;
})
};
loadPersonsData(); //first load
$scope.$on('update', function () {
loadPersonsData(); // load after update of any person
});
}
Try with $scope.$digest(); or use $http instead jQuery ajax or others
Related
So my ui bootstrap model window is working correctly but when I add an object to the controller it stops showing and it doesn't give me any error in consol.
When my controller looks like this:
"use strict";
app.controller('RegisterModalCtrl', ['$scope', '$location', '$uibModalInstance', '$http', 'ngAuthSettings', 'registerService',
function($scope, $location, $uibModalInstance, $http, ngAuthSettings, registerService) {
var $ctrl = this;
$ctrl.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
/*
$ctrl.registerInfo = {
email: $ctrl.registerData.email,
nick: $ctrl.registerData.nick,
password: $ctrl.registerData.password,
password_confirmation: $ctrl.registerData.confirm_password
};
*/
$ctrl.registerSubmit = function(registerInfo) {
console.log('im in registerSubmit controller function');
registerService.registerUser(registerInfo);
$uibModalInstance.dismiss('cancel');
};
$ctrl.showCookiesRules = function() {
$location.url("/cookiesrules");
$uibModalInstance.dismiss('cancel');
};
$ctrl.showRules = function() {
$location.url("/rules");
$uibModalInstance.dismiss('cancel');
};
}]);
Everything works just fine but when i delete /* just before registerInfo object it stops showing. What is wrong with this object? I want it to create this object to pass it in function and then pass it to function in service.
So what you should do is initiate $ctrl.registerInfo:
$ctrl.registerInfo = {};
The data doesn't exist when the controller runs, so you are trying to set the properties of $ctrl.registerInfo without non-existent data. Once your form is filled out, the properties/data will be set.
An alternative option would not be to initialize at all, and simply set your form model to registerData.confirm_password, and when you call registerSubmit, call it with registerSubmit(registerData). That will send the data to that method without having to initialize in the controller:
<input type="text" placeholder="powtórz hasło"
ng-model="registerData.confirm_password" />
<!-- abbreviated (other form fields here -->
<input type="submit" ng-click="registerSubmit(registerData)" />
If you need the data afterwards, in registerSubmit, add a line:
$ctrl.registerInfo = registerInfo;
However, I am not sure you'd want to hang onto the password there.
AngularJS Form Docs: https://docs.angularjs.org/guide/forms
I have a controller HomeworkPageController where I get all the topics from MongoDB using method getAllMainTopics from TopicService. $scope.topics is then used to show all topics. I have a button that open a modal where a new topic is add in MongoDB. The modal is using another controller AddTopicController. How can I update $scope.topics from HomeworkPageController in AddTopicController ? I want to do this because after I close the modal, the list of all topics should be refreshed, it must contain the topic that has been added. I tried to use HomeworkPageController in AddTopicController and then call the method getAllMainTopics but the $scope.topics from html is not updated. Thanks.
Here is HomeworkPageController:
app.controller('HomeworkPageController', ['$scope','TopicService',
function ($scope, TopicService) {
$scope.topics = [];
$scope.getAllMainTopics = function () {
TopicService.getAllMainTopics('homework')
.success(function(data) {
$scope.topics = data;
}
$scope.addTopic = function () {
ModalService.openModal({
template: "templates/addTopic.html",
controller: 'AddTopicController'
});
}
]);
Here is AddTopicController:
app.controller('AddTopicController', ['$scope','$controller', '$timeout','TopicService', '$modalInstance',
function ($scope, $controller, $timeout,TopicService, $modalInstance) {
var homeworkPageController = $scope.$new();
$controller('HomeworkPageController',{$scope : homeworkPageController });
$scope.save = function() {
TopicService.saveTopic(data)
.success(function(result){
homeworkPageController.getAllMainTopics();
$modalInstance.close();
})
}
}]);
Here is the view where I use $scope.topics:
<div class="homework-content-topic-list" ng-repeat="topic in topics">
<label> {{ topic.subject }} </label>
</div
You should probably keep your list of topics in a service and then inject that service into both controllers. This way you would be able to access and update the topics in both of your controllers. It could look something like
app.controller('HomeworkPageController', ['$scope','TopicService',
function ($scope, TopicService) {
$scope.topics = TopicService.topics;
// Do stuff here
]);
Then you just need to modify your TopicService to have it's methods work on the stored object.
you can solve this by two methods
1)look at the example given in ui-bootstrap's website. They have given an example that will suit your requirement - plunker. There are three items in the modal - item1, item2, item3. If you select one of those items and click 'ok', the selected item is sent to the main controller through "resolve" attribute in the $scope.open function.
2)You can write a custom service that acts as a bridge to the two controllers and you can write getter and setter methods in the service.
angular.module('app').service('popupPageService', function() {
var topics;
var setDetails = function(param) {
topics = param;
};
var getDetails = function() {
return topics;
};
return {
setDetails: setDetails,
getDetails: getDetails,
};
});
call the setDetails function in the AddTopicController and once when you come out of the modal, update your $scope.topics in HomeworkPageController by pushing the new value added (getDetails)
I have a AngularJS app with a service that load a HTTP request, that works all fine, but...
When my app is offline at the beginning, i show a "offline" page with a retry button, when i click the button and the APP is online I need the service to load the data.
The problem is that nothing happen when I click the button, the online check works fine but the web service is never called :(
my service:
.service('webService', function ($http, $q){
var defferer = $q.defer()
var webservice_url = "http://mywebservice_url/";
$http.get(webservice_url+"?action=get_settings").success(function(data) {
defferer.resolve(data);
});
return defferer.promise;
})
my controller:
.controller('NetworkCtrl', function($scope, $location, $timeout, webService) {
$("#tryagain-button").click(function(e) {
e.preventDefault();
if(checkifonline()) {
webService.then(function(data) {
$scope.data = data;
});
}
});
})
First of all, using jQuery within an controller is absolutely not how angularjs works. Use the ng-click directive. Even if your service would be implemented correctly, it wouldn't work since AngularJS will not get notified about model changes in the scope (you would need to use $apply, but just stick to the ng-click directive)
Second, the service function takes a constructor function. Within this constructor you're making an http request (while you're offline) and the promise is resolved. You will never make a new request, since the service always retuns the same promise. Your service should look like:
.service('webService', function ($http){
var webservice_url = "http://mywebservice_url/";
this.getSettings = function(){
return $http.get(webservice_url+"?action=get_settings");
};
})
and your controller:
.controller('NetworkCtrl', function($scope, $location, $timeout, webService) {
$scope.onClick = function(){
webService.getSettings().success(function(data){
$scope.data = data;
}
}
})
and your HTML button:
<button ng-click="onClick()">reload</button>
I have a content controller and a header controller in my Angular app. The content controller has the ability to add items to array of objects. The header controller puts these items into the navigation.
On load the header controller successfully loads the existing items from the database and adds them to the global scope, they then show up in the nav thanks to an ng-repeat.
When the content controller adds a new item to the global scope though it's not reflected in the header. I can log out the contents of the global scope and the new item is there, it just doesn't want to show up in the dom. Using $apply() doesn't seem to make any difference.
Here's the 2 controllers:
HeaderCtrl:
angular.module('system').controller('HeaderController', ['$scope', 'Global', 'Lists', function ($scope, Global, Lists) {
$scope.global = Global;
$scope.find = function() {
Lists.query(function(lists) {
$scope.global.lists = lists;
});
};
}]);
ContentCtrl:
angular.module('lists').controller('ListsController', ['$scope', '$routeParams', '$location', '$http', 'Global', 'Lists', function ($scope, $routeParams, $location, $http, Global, Lists) {
$scope.global = Global;
$scope.create = function() {
var list = new Lists({
name: this.name,
});
list.$save(function(response) {
$location.path('lists/' + response._id);
$scope.global.lists.push(response);
});
};
}]);
Like I say a console log from the Header Controller shows that the new item is present in $scope.global.lists but it doesn't get reflected in the DOM. Any ideas?
Use a $rootScope event and catch it in the header whenever you update the other controller:
//main ctrl
$rootScope.$broadcast("updateHeader", someInfoToSend);
//header ctrl
$scope.$on("updateHeader", function(e, someInfoReceived){
// do the necessary updates here
});
It was a small data mismatch between existing items and the newly added item that was causing the issue.
The items from the database had a property of
owner: {
"_id" : "213876512461"
}
Whereas the data returned from the adding of a new item had
owner: "213876512461"
Because of this an ng-hide directive was incorrectly hiding the newly added item.
I've marked ruedamanuel's answer up, as I've ended up using his $broadcast method to let the main controller update $scope.lists in the header controller, negating the need to use $rootScope or a global variable.
I have a search 'page' in my AngularJS app which essentially consists of a view that holds the search form (and displays the results) and a controller which handles the search request. When the user types in a search query and hits 'Search', the $scope.submit() method is called and I can see the results properly. However, when the user clicks on a result and then goes back to the search page, it is blank. I thought of implementing a $cookieStore-based solution so that the query is stored in a cookie and whenever the user goes back to the search page, it automatically re-runs the previous search so they don't have to do it manually. Problem is, the model updates (search gets run from cookieStore value) but the view stays the same (blank). Here's a sample of my controller:
.controller('SearchCtrl', ['$scope', '$http', '$cookieStore','authService', function($scope, $http, $cookieStore, authService) {
var submitted = false;
$scope.submit = function(query){
$cookieStore.query = query;
submitted = true;
$http.jsonp(url).success(function(data) {
$scope.searchResults = data;
});
}
/*
Rerun query if user has pressed "back" or "home" button automatically:
*/
if(!submitted && $cookieStore.query){
console.log("submitting query from cookie store", $cookieStore.query);
$scope.submit($cookieStore.query);
}
... });
I tried using $scope.$apply() after the auto-search but still no joy. The view just won't update. Any hints you guys could give me? Cheers
You should place $scope.$apply at the end of your callback function. It's because $http makes an async AJAX call and by the time response comes back Angular is already done auto-$applying changes. So when you check the model you see the difference but since Angular is no longer $applying the difference cannot be seen on the view.
So when you add $scope.$apply you will have something like this:
.controller('SearchCtrl', ['$scope', '$http', '$cookieStore','authService', function($scope, $http, $cookieStore, authService) {
var submitted = false;
$scope.submit = function(query){
$cookieStore.query = query;
submitted = true;
$http.jsonp(url).success(function(data) {
$scope.searchResults = data;
$scope.$apply();
});
}
/*
Rerun query if user has pressed "back" or "home" button automatically:
*/
if(!submitted && $cookieStore.query){
console.log("submitting query from cookie store", $cookieStore.query);
$scope.submit($cookieStore.query);
}
... });