I have method in directive here i need to access this method from angularjs service.
For Example:
Service,
angular.module('myServiceModule', []).controller('MyController', ['$scope','notify', function($scope, notify) {}]).service('notify', ['$window',function(win) {
}]);
Directive,
angular.module('docsSimpleDirective', []).controller('Controller', ['$scope', function($scope) {}]).directive('myCustomer', function($scope) {
$scope.enableEditor = function(){
}
return {
template:
};
});
In my project i need to access directive method from angularjs.
For example i have added sample code.
In directive i have enableEditor() method i need to be access this method form my angular services.
I searched on web i did not get proper solution for accessing directive method from angular service.
Related
I'm using angularJS 1.4.9 and ui bootstrap 1.0.3.
I would like to decor uibDatepicker directive but the decorator function is never executed and there is no error or warning message in the console.
See this plunker
var uib = angular.module('ui.bootstrap');
uib.config(function($provide) {
$provide.decorator('uibDatepickerDirective', function($delegate) {
alert('never logs this');
return $delegate;
});
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function() {
var main = this;
main.welcome = 'hello you';
});
Thanks for your help
The decorator function is never executed because you never actually use this directive you are trying to decorate.
Decorator is going to be invoked only when the directive is requested by real element in template. This is because services and directives are lazily configured (providers) so provider will not be active unless the service or directive is requested.
Here is an example of it being called when you put directive tag in template. Try adding this line in your code:
<uib-datepicker ng-model="dt" class="well well-sm"></uib-datepicker>
Demo: http://plnkr.co/edit/p4Hcgz83wv9d1WOl6eGo?p=preview
I am trying to load a template file in an AngularStrap popover, however I am having trouble using $templateCache. I seem to be a step further back than the other SO questions, hence this seemingly double one.
Following the API docs I added a <script type="text/ng-template" id="popoverTemplate.html"></script> right before the closing </body> tag. When I use <div ng-include="'popoverTemplate.html'"></div> on my page, I get nothing. If I try using console.log($templateCache.get("popoverTemplate.html")) I get "$templateCache is not defined", which leads me to assume I am missing a crucial step. However, I can't find how to do it in the docs or other SO questions.
EDIT:
Injecting the service was the missing link. However, when I inject the service, the controller's other function no longer works, but if you inject al the function's parameters the working code becomes:
(function() {
"use strict";
angular.module("app").controller("managerController", ["$scope", "imageHierarchyRepository", "$templateCache", function ($scope, imageHierarchyRepository, $templateCache) {
imageHierarchyRepository.query(function(data) {
$scope.hierarchies = data;
});
var template = $templateCache.get("popoverTemplate.html");
console.log(template);
}]);
})();
To use the template script tag . You have to insert it inside the angular application. That is inside the element with the ng-app attribute or the element used to bootstrap the app if you don't use the ng-app tag.
<body ng-app="myapp">
<div ng-template="'myTemplate.html'"></div>
<script type="text/ng-template" id="myTemplate.html">
// whate ever
</script>
</body>
If you want to retrieve the template on a component of the application then you need to inject the service where you want to consume it:
controller('FooCtrl', ['$templateCache', function ($templateCache) {
var template = $templateCache.get('myTemplate.html');
}]);
Or
controller('FooCtlr', FooCtrl);
FooCtrl ($templateCache) {};
FooCtrl.$inject = ['$templateCache'];
EDIT
Do not register two controllers with the same name because then you override the first one with the last one.
(function() {
"use strict";
angular.module("app").controller("managerController",["$scope", "imageHierarchyRepository", "$templateCache", function ($scope, imageHierarchyRepository, $templateCache) {
var template = $templateCache.get("popoverTemplate.html");
console.log(template);
imageHierarchyRepository.query(function(data) {
$scope.hierarchies = data;
});
}]);
})();
Small addition: Although there are few ways to achieve your goals, like wrapping your whole HTML in <script> tags and all that, the best approach for me was to add the $templateCache logic into each Angular directive. This way, I could avoid using any external packages like grunt angular-templates (which is excellent but overkill for my app).
angular.module('MyApp')
.directive('MyDirective', ['$templateCache', function($templateCache) {
return {
restrict: 'E',
template: $templateCache.get('MyTemplate').data,
controller: 'MyController',
controllerAs: 'MyController'
};
}]).run(function($templateCache, $http) {
$http.get('templates/MyTemplate.html').then(function(response) {
$templateCache.put('MyTemplate', response);
})
});
Hope this helps!
I am trying to run an $http function when my AngularJS application first loads.
This $http function needs to finish before any of the controllers in my application could properly function. How would I go about doing this? This sounds like a promise, but it sounds like I would be creating a promise in each controller...
I currently have the function that I want to run first like this:
app.run(function() {
$http.get('link').success(function(data) {
// success function. The data that I get from this HTTP call will be saved to a service.
}).error(function(error) {
});
});
However, sometimes the controller will load before the http call finishes.
The problem
Angular is not dynamic, you cannot add controller dynamically neither factory, etc. Also you cannot defer controller bootstrap, angular loads everything together, and it's quite disadvantage (will be fixed in Angular 2)
The cure
But javascript itself has very important feature - closure, which works anywhere, anytime.
And angular has some internal services that can be injected outside of angular ecosystem, even into browser console. Those services injected as shown below. We technically could use anything else (jQuery.ajax, window.fetch, or even with XMLHttpRequest), but let's stick with total angular solution
var $http_injected = angular.injector(["ng"]).get("$http");
The act
First of all, we defer whole angular app bootstrap, inject http service. Then you make your needed request, receive data and then closure get's to work, we pass received data into some service, or we could also assign in to some angular.constant or angular.value but let's just make demo with angular.service, so when your service has data, bootstrap whole app, so that all controllers get initialized with your needed data
Basically that kind of tasks solved like this
<body>
<div ng-controller="Controller1">
<b>Controller1</b>
{{text}}
{{setting.data.name}}
</div>
<hr>
<div ng-controller="Controller2">
<b>Controller2</b>
{{text}}
{{setting.data.name}}
</div>
<script>
//define preloader
var $http_injected = angular.injector(["ng"]).get("$http");
$http_injected.get('http://jsonplaceholder.typicode.com/users/1').then(function(successResponse) {
//define app
angular.module('app', []);
//define test controllers
//note, usually we see 'controller1 loaded' text before 'settings applied', because controller initialized with this data, but in this demo, we will not see 'controller1 loaded' text, as we use closure to assign data, so it's instantly changed
angular.module('app').controller('Controller1', function($scope, AppSetting) {
$scope.text = 'controller1 loaded';
$scope.setting = AppSetting.setting;
$scope.$watch('setting', function(e1 ,e2){
$scope.text = 'settings applied'
});
});
angular.module('app').controller('Controller2', function($scope, AppSetting) {
$scope.text = 'controller2 loaded';
$scope.setting = AppSetting.setting;
$scope.$watch('setting', function(e1 ,e2){
$scope.text = 'settings applied'
});
});
//define test services, note we assign it here, it's possible
//because of javascript awesomeness (closure)
angular.module('app').service('AppSetting', function() {
this.setting = successResponse;
});
//bootstrap app, we cannot use ng-app, as it loads app instantly
//but we bootstrap it manually when you settings come
angular.bootstrap(document.body, ['app']);
});
</script>
</body>
Plunker demo
You can do this when you configure your routes
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
controller: 'MainCtrl',
templateUrl: 'main.html',
resolve: {
data: ['$http',
function($http)
{
return $http.get('/api/data').then(
function success(response) { return response.data.rows[0]; },
function error(reason) { return false; }
);
}
]
}
});
}]);
Similar question:
AngularJS - routeProvider resolve calling a service method
AngularJS: $routeProvider when resolve $http returns response obj instead of my obj
Heres a plunkr I found using a service, which is what I would recommend.
http://plnkr.co/edit/XKGC1h?p=info
I have a Controller which has something like this...
angular.module('kZoneApp').controller('DemandController', ['$http', '$scope', '$rootScope', 'dataFactory', '$window', '$routeParams','$sce', function ($http, $scope,$rootScope, dataFactory, $window, $routeParams,$sce) {
$scope.channel = $routeParams.channel;
now within my page.html, I want to do the following....
<script>
YoutubeVideoPlayer.openVideo('{{channel}}');
</script>
please note, I am using Routes, and page.html is loaded into my ng-view Via a Route.
<div id="myView" class="reveal-animation" ng-view></div>
I tried below code, but it returns undefined....
$().ready(function () {
var channel = angular.element("#myView").scope().channel
YoutubeVideoPlayer.openVideo(channel);
})
How can I get the value of Channel within my Template View?
Update
below works...but I am sure there has to be a cleaner solution
setTimeout(function () {
alert(angular.element("#myView").scope().channel)
}, 500);
A workaround solution should be creating a variable before your Angular.module definition.
var scopeInAngular = null;
and inside controller assign controller to your variable.
scopeInAngular = $scope;
then if you manipulate anything inside angular view use
scopeInAngular.$apply();
I need current path from url in template (content of $location.path). But not via controller, because I have a lot of controllers (and I do not want to duplicate declaration of $scope.currentUrl = $location.path;). Thanks for the advice.
AngularJS template can only see what is available in a scope so you will need somehow to put $location service in a scope. There is one scope that is always available in AngularJS application called $rootScope so it could be use for your use-case.
What you could do is to use run() method of a module to expose $location in the $rootScope:
var myApp = angular.module('myApp', []).run(function($rootScope, $location) {
$rootScope.location = $location;
});
this would make 'location' available in all templates so later on you could do in your template:
Current path: {{location.path()}}
An alternative is to use the more semantic and versatile ui-router, then in the controller, retrieve the current state, and store it on the $scope:
app.controller('MyCtrl', ['$scope', '$state', function MyCtrl($scope, $state) {
$scope.state = $state.current.name;
...
}