Parent view does not get updated - angularjs

I am using angular with ngDialog. I have in my view a list of users with an edit button which opens the user details in a ngDialog. Now when i save the data in my ngDialog I would like the list of users to be updated.
I thought to use a observer pattern for this. However the handler doesn't fire.
Here is my code:
User Controller
angular.module('myApp')
.controller('UserController', function($scope, User){
//this method gets fired when the dialog is saved
$scope.update = function(user)
{
User.update(user);
$scope.$broadcast('refresh-users');
return true;
}
});
UsersController:
angular.module('myApp')
.controller('UsersController', function($scope, User, ngDialog){
var loadUsers = function(users) {
$scope.users = users;
}
var handleErrors = function(response) {
console.error(response)
}
$scope.userPopup = function(id)
{
ngDialog.open(
{
template:'../partials/user.html',
controller: 'UserController',
data: {'id': id},
scope: $scope
});
}
$scope.$on('refresh-users', function handler(){
console.log('handler');
User.getAll()
.then(loadUsers)
.catch(handleErrors);
});
});
How could I solve this?

Use $rootScope instead of $scope as these two controllers are not using the same scope.

As has already been mentioned you want to use $rootScope for broadcasting if what you're trying to communicate is on another scope.
User Controller
angular.module('myApp')
.controller('UserController', function($scope, $rootScope, User){
//this method gets fired when the dialog is saved
$scope.update = function(user)
{
User.update(user);
$rootScope.$broadcast('refresh-users');
return true;
}
});
UsersController:
angular.module('myApp')
.controller('UsersController', function($scope, $rootScope, User, ngDialog){
var loadUsers = function(users) {
$scope.users = users;
}
var handleErrors = function(response) {
console.error(response)
}
$scope.userPopup = function(id)
{
ngDialog.open(
{
template:'../partials/user.html',
controller: 'UserController',
data: {'id': id},
scope: $scope
});
}
$rootScope.$on('refresh-users', function handler(){
console.log('handler');
User.getAll()
.then(loadUsers)
.catch(handleErrors);
});
});

Related

How to call function of one controller from another controller AngularJs

I have two controller name called like:
AutoLoginCtrl
LoginCtrl
my facebook logout function present in Login Controller, from AutoLogin controller how could I call logout function which is Login Controller.
I have tried like this by using $rootscope and $on
LoginCtrl.js
ionApp.controller('LoginCtrl', function($scope, $state, $ionicModal, $rootScope, $q, $timeout, UserService, $ionicLoading, $ionicActionSheet) {
$scope.showLogOutMenu = function() {
var hideSheet = $ionicActionSheet.show({
destructiveText: 'Logout',
titleText: 'Are you sure you want to logout? This app is awsome so I recommend you to stay.',
cancelText: 'Cancel',
cancel: function() {},
buttonClicked: function(index) {
return true;
},
destructiveButtonClicked: function() {
$ionicLoading.show({
template: 'Logging out...'
});
// Facebook logout
facebookConnectPlugin.logout(function() {
$ionicLoading.hide();
$state.go('login');
},
function(fail) {
$ionicLoading.hide();
});
}
});
};
$rootScope.$on("LogoutFunction", function(){
$scope.parentmethod();
});
})
AutoLoginCtrl
ionApp.controller('AutoLoginCtrl', function($scope, $state, $ionicModal, $rootScope, $q, $timeout, UserService, $ionicLoading, $ionicActionSheet) {
var checkPage = "home";
$scope.logout = function() {
$rootScope.$emit("LogoutFunction", {});
}
})
You decided to use $emit a.e. child controller notifies parent controller. Is it true? AutoLoginCtrl is a child of LoginCtrl or maybe you need to use $broadcast instead?
The second problem might be:
For some reason LoginCtrl still didn't load and no one listens on LogoutFunction event.
Please check these cases
you can make a Public Class (Provider Maybe) and make a function in it that call a function 'Logout()' from 'LoginController'
and call this provider function in Your 'AutoLogin' Controller
You can have the logout function in a factory and call it from both the controllers, like this.
Factory basic demo: here
Code:
ionApp.controller('LoginCtrl', function($scope, $ionicModal, $rootScope, $q, $timeout, UserService, SharedService) {
$scope.showLogOutMenu = function() {
SharedService.logout();
};
}).factory('SharedService', function ($ionicActionSheet, $ionicLoading, $state) {
return {
logout: function () {
var hideSheet = $ionicActionSheet.show({
destructiveText: 'Logout',
titleText: 'Are you sure you want to logout? This app is awsome so I recommend you to stay.',
cancelText: 'Cancel',
cancel: function() {},
buttonClicked: function(index) {
return true;
},
destructiveButtonClicked: function() {
$ionicLoading.show({
template: 'Logging out...'
});
// Facebook logout
facebookConnectPlugin.logout(function() {
$ionicLoading.hide();
$state.go('login');
},
function(fail) {
$ionicLoading.hide();
});
}
});
}
}
}).controller('AutoLoginCtrl', function($scope, $ionicModal, $rootScope, $q, $timeout, UserService, SharedService) {
var checkPage = "home";
$scope.logout = function() {
SharedService.logout();
}
});

angularjs modal service broadcast and on issue

I am using angular-modal-service library. My logic is : when the modal is open it runs a function from SomeService, and $rootScope.$broadcast from SomeService to modal controller that way I can send resource from service to my modal controller. However, it doesn't fire. Please help me to figure out what I have missed. Thank you.
**Service: **
angular.module('ng-laravel').service('SomeService', function($rootScope, Restangular, CacheFactory, $http) {
this.testFunction = function() {
console.log("from service");
$rootScope.$broadcast('event', {success:'success'});
};
}
**Controller: **
$scope.show = function(customer_id) {
ModalService.showModal({
templateUrl: 'modal.html',
inputs: {
customer_id: customer_id
},
scope: $scope,
controller: function($scope, close) {
$scope.customer_id = customer_id;
$scope.close = function(result) {
close(result, 500); // close, but give 500ms for bootstrap to animate
};
$scope.$on('event', function(event, data){
alert('yes');
console.log('from modal controller');
});
}
}).then(function(modal) {
SomeService.testFunction(customer_id, tour_id);
modal.element.modal();
modal.close.then(function(result) {
$scope.message = "You said " + result;
});
});
};
After switching the function it works, but...
how could i pass data in to modal? like ui-bs-modal, they have resolve.
You're being broadcasting event before events from modal controller are binding. So before broadcasting event make sure that event listeners are registered(meaning modal controller has been loaded). So call SomeService.testFunction(); after showModal method.
$scope.show = function(customer_id) {
ModalService.showModal({
templateUrl: 'modal.html',
inputs: {
customer_id: customer_id
},
scope: $scope,
controller: function($scope, close) {
//code as is
//listeners will get register from here.
}
})
.then(function(modal) {
SomeService.testFunction(); //broadcasting event
}).catch(function(error) {
// error contains a detailed error message.
console.log(error);
});
};
You are broadcasting the event, before the modal controller is instantiated or created, as service function is called before ModalService.showModal. Try changing the order. That should work fine.
Inside $scope.show try this order
$scope.show = function(){
ModalService.showModal({
....
// Listen for broadcast event
});
SomeService.testFunction();
}

inject service[declared in separate file] in app.config or use it in a controller

I am trying to use the code from here to show routes only when a promise is TRUE
I am following this for my directory structure
app
- Orders
-orders.html
-OrderController.js
-OrderService.js
Main-Config [app.js]
var myApp = angular.module('myApp', ['ngRoute','ngAnimate','ui.bootstrap','myApp.OrderController']);
myApp.config(function($routeProvider, $locationProvider){
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$routeProvider
.when('/orders', {
templateUrl: 'orders/orders.html',
controller: 'OrderController',
resolve:{
customerExpenses: function(OrderService){
return OrderService.getOrders($route.current.params.customerName);
}
}
})
})
OrderService.js
angular.module('myApp').factory('OrderService', ['$http', function($http) {
var sdo = {
getNames: function() {
var promise = $http({
method: 'GET',
url: ''
});
promise.success(function(data, status, headers, conf) {
return data;
});
return promise;
}
}
return sdo;
}]);
I have tried the Accepted answer from here, and one of the suggestion from another SO article
angular.module('myApp')
.service('FooService', function(){
//...etc
})
.config(function(FooServiceProvider){
//...etc
});
As I have my service in a different file, I am trying to determine if I can use it in app.js file without using provider or is that the only way to use service in app.config?
UPDATE 1:
If i want to use the service in a controller
angular.module('myApp.OrderController',[]).controller('OrderController', function ($scope) {
$scope.displayed=[];
$scope.displayed.push(OrderService.getNames());
});
I get OrderService not available
Have tried this:
angular.module('myApp.OrderController',[]).controller('OrderController', ['$scope','OrderService',function ($scope) {
$scope.displayed=[];
$scope.displayed.push(OrderService.getNames());
}]);
followed example :
angular.
module('myServiceModule', []).
controller('MyController', ['$scope','notify', function ($scope, notify) {
$scope.callNotify = function(msg) {
notify(msg);
};
}]).
factory('notify', ['$window', function(win) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join("\n"));
msgs = [];
}
};
}]);
but can not use my service. my controller and service are in different files
I added this question here as I feel they are somewaht related.
You have not injected your service OrderService, change your code in very first line
var myApp = angular.module('myApp', ['ngRoute','ngAnimate', ....'OrderService'])
myApp.config(function($routeProvider, $locationProvider, OrderService){
....
})
Rest of the code looks good

AngularUI modal dialog - calling dialog's controller function on "rendered" event

I would like to call dialog's controller function on $modal.rendered event, is this doable without polluting $scope?
Here is a sample Plunkr:
http://plnkr.co/edit/HzFe65RY3hNme8QuUWaJ?p=preview
So, in promise:
modalDialog.rendered.then(function () {
demo.message = 'Dialog opened';
});
I would like to call onLoaded function from modalController controller.
Thank you, best regards,
You can use a factory/service to share data & functions across controllers;
angular.module('app', ['ui.bootstrap'])
.controller('demoController',['$modal', 'modalService', function($modal, service) {
var demo = this;
demo.message = 'It works!'
demo.modal = function() {
var modalDialog = $modal.open({
controller: 'modalController',
controllerAs: 'modal',
templateUrl: 'modal.html'
});
modalDialog.rendered.then(function () {
demo.message = 'Dialog opened';
service.onLoaded();
});
};
}])
.controller('modalController', ['$modalInstance', 'modalService', function($modalInstance, service) {
var modal = this;
service.modalText = 'Modal Text';
modal.shared = service;
modal.cancel = function() {
$modalInstance.dismiss();
}
}])
.factory('modalService', function() {
var service = {
modalText: 'Modal text',
onLoaded: onLoaded
};
return service;
function onLoaded() {
service.modalText = 'Modal loaded';
}
})
And the following update to the html;
<div class="modal-body">
<pre>{{ modal.shared.modalText }}</pre>
</div>
Updated plunker: http://plnkr.co/edit/q704IjkHSAYwuCfLuYnU?p=preview

Angular controller get model asynchronously

I have a controller that starts like this (simplified for this question):
angular.module('myApp.controllers')
.controller('MyController', ['$scope', '$routeParams', 'MyService',
function ($scope, $routeParams, MyService) {
MyService.fetchWithId($routeParams.id).then(function(model) {
$scope.model = model;
});
Which is fine, but then in many places throughout the controller, I have functions that are referred to in the view that refer to the model ...
$scope.someFunctionMyViewNeeds = function() {
return $scope.model.someModelAttribute;
};
Since these often run before the fetch completes, I end up with errors like "cannot read property of undefined" when the view tries to see someModelAttribute.
So far, I've tried three things:
// before the fetch
$scope.model = new Model();
...but I really don't want a new model, and in some cases, cannot complete initialization out of the blue without other dependences.
Another idea is to litter the code with defense against the unready model, like:
return ($scope.model)? $scope.model.someModelAttribute : undefined;
... but that's a lot of defense all over the code for a condition that only exists while the fetch completes.
My third idea has been to "resolve" the model in the route provider, but I don't know how to do that and get at the $routeParams where parameter to fetch the model is kept.
Have I missed a better idea?
Try this if you want to use resolve.
var app = angular.module('app', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider.when('/things/:id', {
controller: 'ThingsShowController',
resolve: {
model: function ($routeParams, MyService) {
return MyService.fetchWithId(+$routeParams.id);
}
},
template: '<a ng-href="#/things/{{model.id}}/edit">Edit</a>'
});
$routeProvider.when('/things/:id/edit', {
controller: 'ThingsEditController',
resolve: {
model: function ($routeParams, MyService) {
return MyService.fetchWithId(+$routeParams.id);
}
},
template: '<a ng-href="#/things/{{model.id}}">Cancel</a>'
});
});
// Just inject the resolved model into your controllers
app.controller('ThingsShowController', function ($scope, model) {
$scope.model = model;
});
app.controller('ThingsEditController', function ($scope, model) {
$scope.model = model;
});
// The rest is probably irrelevant
app.factory('Model', function () {
function Model(attributes) {
angular.extend(this, attributes);
}
return Model;
});
app.service('MyService', function ($q, Model) {
this.fetchWithId = function (id) {
var deferred = $q.defer();
deferred.resolve(new Model({ id: id }));
return deferred.promise;
};
});
// Just to default where we are
app.run(function ($location) {
$location.path('/things/123');
});
app.run(function ($rootScope, $location) {
$rootScope.$location = $location;
});
// Because $routeParams does not work inside the SO iframe
app.service('$routeParams', function () {this.id = 123;});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.9/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.9/angular-route.min.js"></script>
<div ng-app="app">
<div>Route: {{$location.path()}}</div>
<div ng-view=""></div>
</div>

Resources