I have a problem.
.controller('A_Ctrl', function($scope){
$scope.getdata = function(){
console.log("ok");
}
})
I want to execute the function $scope.getdata() when view change by this view each time.
But this function is executed only once when change view by this view at first time.
My suggestion is possible in angularjs?
You forget to call the function, add the following sentence:
$scope.getdata();
Another solution: wrap it in a $rootScope and use a $location if you
want more control and based on the url you can
call getdata() or not.
var app = angular.module('app', [])
.run(function($rootScope, $location) {
$rootScope.$on('$routeChangeStart', function() {
$rootScope.getdata();
});
})
.controller('A_Ctrl', function($rootScope){
$rootScope.getdata = function(){
console.log("ok");
};
$rootScope.getdata(); //----- missed line
});
But I recommend the first approach.
Make the function self-executing.
($scope.getdata = function(){
console.log("ok");
})();
Related
I was looking on the internet but did not see a definitive answer. So here is my case:
The code is written by head so excuse for not being complete
I have a page that looks something like:
<div ng-controller="myController">
<my-customer my-callback="directiveCallback(item)" />
</div>
I then have a script that looks like this:
var app = angular.module('myApp', []);
app.controller('myController', ['$scope', 'apiService', function($scope, apiService) {
apiResponse = apiService.getAll('myRepo');
apiResponse.then(function(d){
$scope.data = d;
})
$scope.directiveCallback = function(item) {
// do stuff with $scope.data
}
}])
.directive('myCustomer', function() {
return {
scope: {
myCallback:'&'
},
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
The thing is the service promise resolves and returns some data.
The directive controller is calling another service that returns some data and fires the call back when it is done with the data that it recives.
When he lands on the callback function the item is attached to the $scope.data.
The problem was that the callback is triggered before $scope.data is populated.
I curently salved this so that I wraped the callback in a $timeout with a settable delay via a direcitve parameter.
Is that is correct way to do it or is there a better way?
Hmm, doesnt this simply work:
$scope.directiveCallback = function(item) {
apiResponse.then(function() {
console.log($scope.data); // always updated
// do whatever
})
}
I have my notification listener in the run function. When a notification is received I need to update a object present in $scope with a parameter present in notification object.
angular.module('app', ['ionic', 'chatsCtrl'])
.run(function($state, $ionicPlatform) {
window.FirebasePlugin.onNotificationOpen(function(notification) {
// Need to append this notification.parameter to a scope variable present in a controller
}
}
.controller('chatsCtrl', function($scope) {
// $scope.chats
});
How can I go about doing this? I don't want to use $rootScope object as $scope.chat object will get very heavy.
Thanks
you can't call scope variables/functions inside run block. since you don't want to use rootscope my suggestion is to create a service and assign values to a particular method in that service from the run block. Then get that value from the controller using the same service.
angular.module('app', ['ionic', 'chatsCtrl'])
.run(function($state, $ionicPlatform) {
window.FirebasePlugin.onNotificationOpen(function(notification) {
sampleService.setData(notification)
}
}
.controller('chatsCtrl', function($scope,sampleService) {
$scope.chats = sampleService.getData()
});
.factory('sampleService', function() {
var data;
return {
getData : function(){ return data},
setData: function(param){ data = param},
}
});
I have simple controller with one method:
app.controller('MyApp', function($scope) {
$scope.myMethod() {...}
}
I have also many components for input fields (for example for text input, number input, checkbox, radio etc.):
app.component('TextInput', {
template: "<input type='text' ng-change='$ctrl.myMethodInComponent()' ng-model='inp' />",
bindings: {
myMethod: '&',
},
controller: function() {
var ctrl = this;
ctrl.myMethodInComponent = function() {
/* some customizations */
ctrl.myMethod();
}
}
});
I create this input in following way:
<text-input myMethod="myMethod()"></text-input>
Everything works as expected, but the problem is that I have many components which want to use method 'myMethod' from main controller and I don't want to transfer it to each component using bindings ('&').
Rather I want to have this method in something like mainScope. I know that Angular provides rootScope but I don't have idea how to use it in my case. Is there possibility to attach 'myMethod' to some main (root) scope which will be shared between all my components?
What you want to do can be achieved by using services and factories. Take alook into it, and if you need help or a template, just ask me.
EDIT template
app.factory('myFactory', function($scope)
var ret = {
myMethod: myMethod,
myMethodWithParams: myMethodWithParams
}
return ret;
function myMethod() {...}
function myMethodWithParams(param1, param2) {...}
}
And now, in your controllers, you can use it as a dependency
app.controller('myController', function(myFactory) {
var x = myFactory.myMethod();
var y = myFactory.myMethodWithParams('hello', 'world');
});
Not sure this is the sort of use case you are looking for using $rootScope, but here's a solution along those lines:
angular.module('myApp', [])
.controller('MyController', function ($scope, $rootScope) {
$scope.message = 'Hello from Controller 1';
$scope.$watch('message', function () {
$rootScope.$emit('controller1_scope_change', {
message: $scope.message
});
});
}).controller('MyController2', function ($scope, $rootScope) {
$scope.message = 'Hello from Controller 2, here is the output from Controller 1:';
$rootScope.$on('controller1_scope_change', function (event, args) {
console.log('arguments received by the handler for the event: ', args);
$scope.message2 = args.message;
});
// really hacky way of doing it
/*var controller1_scope = angular.element(document.querySelector('#controller1')).scope();
controller1_scope.$watch(function () {
$scope.message2 = controller1_scope.message
});*/
});
View example here on codepen
I need to cover this service 100% in jasmine test but it didn't let me cover the controller.
Here's the service for dialog:
(function () {
'use strict';
angular.module('core.dialog').service('dialog', ToasterService);
ToasterService.$inject = ['$translate', '$mdDialog'];
function ToasterService($translate, $mdDialog) {
this.show = function (key, values) {
$translate(key, values).then(function (message, $event) {
$mdDialog.show({
controller: DialogController,
templateUrl: 'app/common/core/dialog/dialog.html',
targetEvent: $event,
locals: {
message : message
}
});
function DialogController($scope, $mdDialog, message) {
$scope.message = message;
$scope.closeDialog = function() {
$mdDialog.hide();
};
}
});
};
}
})();
but when I run the code coverage report it didn't cover the DialogController function.
Can somebody help me with this? Thanks in advance.
This is an old question, but in case anyone is wondering how this might be solved, here is a way, one of several. I would create the controller with angular, move it out of the service, so you can unit test only the controller. Then spyOn $mdDialog.hide and make sure it was called. Assuming the DialogController(...) is moved out of service so it is visible.
angular.module('example')
.controller('DialogController' DialogController);
Then, when setting up your test store $mdDialog for spying later, you also need $q or whatever promises you want to use if you are doing anything with the promise returned from hide().
var mdDialog, q;
beforeEach(inject(function ($injector) {
mdDialog = $injector.get("$mdDialog");
q = $injector.get("$q");
Then you create your controller and $rootScope.$digest(), which is covered elsewhere in-depth.
And finally in your tests:
spyOn(mdDialog, 'hide').and.callFake(function(){
var deferred = q.defer();
deferred.resolve();
return deferred.promise;
});
// TODO: call your closeDialog() controller function here (may need to call $apply)
expect(mdDialog.hide).toHaveBeenCalled();
Is it possible to use dependency injection to reference a controller inside of a filter? I tried the following:
app.filter('myFilter', function(MyCtrl) {...})
app.controller('MyCtrl', function(...) {})
But I get an error that MyCtrl dependency cannot be found.
If you are trying to access some sort of state information inside your filter, you should consider moving that functionality into a service and then accessing the service from both your filter and your controller.
I can't come up with a reason to want to instantiate a controller inside a filter, so perhaps if you gave a bit more background about the problem you are trying to solve we could give you more tailored information on how best to implement it.
In any case, here's a Plunk showing a filter and a controller sharing some data:
app.controller('MainCtrl', function($scope, MyService) {
$scope.text = "ABCDEFG";
$scope.data = 2;
$scope.$watch('data', function() {
MyService.setData($scope.data);
})
});
app.service('MyService', function() {
service = {}; // the service object we'll return
var dataValue = 'data';
service.setData = function(data) {
dataValue = data;
}
service.getData = function() {
return dataValue;
}
return service;
});
app.filter('truncate', function(MyService) {
return function(input) {
return input.substring(0, MyService.getData());
};
});
If you check out the plunk, note that you have to update the text to get the filter to re-run with an updated number of characters to show.
actually this is the way:
Just inject $filter to your controller
.controller('myController', function($scope, $filter) {...});
Then it does not matter where you want to use that filter, just use it like this:
$filter('filterName');
If you want to pass arguments to that filter, do it using separate parentheses:
.controller('myController', function($scope, $filter) {
$filter('filterName')(argument1,argument2);
});