Trying to inject an Angular module to my main module using oclazyload. Please note, I am not using RequireJs or oclazyload to load the JavaScript file currently.
For now I added the module inside Index HTML Script tag.
The inject method executes without any error. But when I log $ocLazyLoad.getModules(), I don't see the module I wanted to inject.
Any help greatly appreciated.
Inline Script:
<script type="text/javascript">
var app = angular.module("ngNextGenWidget", []); //This is the module to be injected
app.factory('nextGenWidget', function () {
return {
constructControl: function ($compile, $scope) {
//Compile html fragment
var compileFunction = $compile("<div tools-Home-Page></div>")
//Get html output from directive after applying $scope
var htmloutputFromDirective = compileFunction($scope);
return htmloutputFromDirective;
}
}
});
app.directive('toolsHomePage', function () {
return {
restrict: 'A',
scope: true,
templateUrl: '/Content/Templates/DemoTemplate-1.html',
controller: ['$scope', function ($scope) {
$scope.name = 'Home Page';
}]
}
});
</script>
Main app:
appLazy.directive('testComponent', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
scope.Execute(attrs, element, attrs.moduleName);
},
controller: ['$scope', '$compile', '$ocLazyLoad',
function ($scope, $compile, $ocLazyLoad) {
$scope.Execute = function (attr, element, moduleName) {
$ocLazyLoad.inject(moduleName);//trying to inject the module
var htmloutputFromDirective =
$nextGenWidget.constructControl($compile, $scope);
$(element).append(htmloutputFromDirective);
}
}]
};
});
Related
I have a directive (DirectiveA), which makes an $http call and creates a new html code.
directiveA
(function(){
angular.module('app').directive('directiveA', directiveA);
})();
(function(){
angular.module('app').controller('DirectiveAController', DirectiveAController);
})();
function directiveA($timeout){
return {
restrict: 'E',
scope: {
url:'#'
},
template: '<div ng-if="template" ng-bind-html="template"></div>',
link: function ( scope, element, attrs ) {
scope.element = element;
},
controller: DirectiveAController
};
}
directiveA.$inject = ['$timeout']
function DirectiveAController($scope, $http, $sce){
$http.get(`${$scope.url}`).then(function(res){
if(res.success){
$scope.template = $sce.trustAsHtml(res.template);
}
});
}
DirectiveAController.$inject = ['$scope', '$http','$sce'];
this works fine.
On the new created element, i want to capture the click function using another directive.
Directive 2
(function(){
angular.module('mcq').directive('captureClick', captureClick);
})();
function captureClick($timeout, $compile){
return {
link: function ( scope, element, attrs ) {
console.log("i am called") // Working on page load but not on dynamic element
scope.element = element;
},
};
}
captureClick.$inject = ['$timeout', '$compile'];
response.template
<button capture-click></button>
Rendered a dummy element of response.template (as static content) and the directive works. How can i get it work on dynamically rendered element.
Using compile my directive is picked up.
(function(){
angular.module('app').directive('directiveA', directiveA);
})();
(function(){
angular.module('app').controller('DirectiveAController', DirectiveAController);
})();
function directiveA($timeout){
return {
restrict: 'E',
scope: {
url:'#'
},
template: '',
link: function ( scope, element, attrs ) {
scope.element = element;
},
controller: DirectiveAController
};
}
directiveA.$inject = ['$timeout']
function DirectiveAController($scope, $http, $sce, $compile){
$http.get(`${$scope.url}`).then(function(res){
if(res.success){
var com = $compile(res.template)($scope);
$scope.element.append(com[0].outerHTML);
}
});
}
DirectiveAController.$inject = ['$scope', '$http','$sce', '$compile'];
Note sure, this is the correct way and has any cons
I'm trying to develop a directive that has it's own controller so it can collect the data it need's from the API and be injected anywhere.
Here's what I got so far:
(function () {
'use strict';
angular
.module('app.hostelsmg.bookings')
.directive('bookingsChart', bookingsChart);
function bookingsChart() {
return {
restrict: 'E',
scope: true,
controller: [function(){
$scope.test = 'Hi there!';
}],
compile: function(tElem, attrs){
tElem.html('{{test}}');
return function(scope, elems, attrs){
}
}
}
}
})();
So what I'd like, is the directive to get data from it's own controller. So far I couldn't get it to work that way.
Does anyone know how?
You can use something like this
function bookingsChart() {
return {
restrict: 'E',
scope: true,
controller: ['$scope', 'yourservice', function ($scope, yourservice) {
$scope.data = []; //bind this data to your view
$scope.getServiceData = function (count) {
//your service call
yourservice.getServiceData(count).then(function (data) {
$scope.data = data; //sets data in $scope.data variable
});
}
}],
link: function (scope, elements, attributes) {
//if you want to pass any parameters from your UI to your service method
scope.getServiceData(attributes.count); //calls the getServiceData in controller defined above
}
}
}
Please help fix the script.
i make simply directive:
angular.module('menus', [])
.directive("epMenu", ['$timeout', '$state',
function ($timeout, $state) {
return {
link: function (scope, element, attrs) {
scope.goTo = function(link) {
console.log('go to', link);
};
var navigationElem = angular.element("<div class='ep-menu-navigation'><li ng-click='scope.goTo('main')'>qwerty</li></div>");
angular.element('body').append(navigationElem);
},
restrict: "EACM"
}
}]);
but it does not work. I need to when you press the button, start function goTo()
Now the console following error message:
VM436 angular.js:12520 Error: [$injector:unpr] Unknown provider: $stateProvider <- $state <- epMenuDirective
live example
$state is a provider that is registered in the ui.router module, so you have to lay that dependency:
angular.module('menus', ["ui.router"])
Also, if you are building the template dynamically in the link function, you have to compile it so that angular can apply its actions to it:
.directive("epMenu", ['$timeout', '$state', '$compile',
function ($timeout, $state, $compile) {
return {
link: function (scope, element, attrs) {
scope.goTo = function(link) {
console.log('go to', link);
};
var navigationElem = angular.element("<div class='ep-menu-navigation'><li ng-click='goTo('main')'>qwerty</li></div>");
$compile(navigationElem)(scope, function(cloned){
angular.element('body').append(cloned);
});
},
restrict: "EACM"
}
}]);
You also had some other errors in your code:
Missing the angular ui router script
Using scope.goTo instead of just goTo
Not escaping the quotes in the goTo function
Using jqLite, you cannot use angular.element('body'), instead use the $document service
Here is a working example.
First of all you should have ui.router injected as dependency to your module.
angular.module('menus',["ui.router"])
If you want to change the state when clicked on a link created by a directive, create a controller for the directive.
use the $state.go in the controller to redirect.
In my answer, I used a controller, which changes the state to menu when clicked on the link of directive.
Here is the code to achieve it,
(function() {
angular.module('menus')
directive('epMenu', function () {
var controller = ['$scope','$state', function ($scope,$state) {
$scope.goTo = function(link) {
$state.go(link)
};
}],
template = "<div class='ep-menu-navigation'><li ng-click='goTo('main')'>qwerty</li></div>";
return {
restrict: 'EA', //Default in 1.3+
controller: controller,
template: template
};
});
}());
The error inside your code is because it does not find dependency for $state. you have to add angular.module('menus', ["ui.router"]) because $state is registered inside ui-router.also you have to add proper js for ui-router. You can bind click event inside link function.
angular.module('menus', ["ui.router"]).directive("epMenu", ['$timeout', '$state',
function($timeout, $state) {
return {
link: function(scope, element, attrs) {
element.find('button').bind('click', function() {
console.log("click");
});
},
restrict: "EACM"
}
}
]);
angular.module('menus',
["ui.router"])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.min.js"></script>
<div ng-app="menus">
<ep-menu>
this is normal text
<button>
Click Me
</button>
</ep-menu>
</div>
I wrote a plunker to see how to use bindToDirective to isolate scopes and using directive controller to call main controller function, but, I am doing something wrong. Could you suggest?
This is the plunker: http://plnkr.co/edit/UJLjTmIiHydHr8qRzAsX?p=preview
Code sample:
.controller('Ctrl', function() {
var self = this;
self.func = function() {
console.log('In the controller function');
};
})
.directive('myDirective', [ function() {
var self = {};
self.link = function (scope, elem, attrs, ctrl) {
elem.bind('click', function () {
ctrl.ctrlFunc();
});
elem.addClass('fa fa-file-excel-o fa-lg');
};
return {
restrict: 'E',
scope: {},
controller: function () {
},
controllerAs: 'DirCtrl',
bindToController: {
ctrlFunc: '&'
},
link: self.link
};
}])
html sample to associate main controller function to directive:
<div ng-controller="Ctrl">
<my-directive ctrlfunc="Ctrl.func()"></my-directive>
</div>
You have a number of issues:
You need a hyphen in your directive argument name and you should be passing the function reference, not calling the function directly (with params):
<my-directive ctrl-func="ctrl.func"></my-directive>
Second, you are using alias syntax in your controller (var self = this;), but not in your template. You need to update it to the following:
<div ng-controller="Ctrl as ctrl">
<my-directive ctrl-func="ctrl.func"></my-directive>
</div>
Finally, pass down the function reference with two-way binding instead of with & since that passes down values for implicit evaluation.
bindToController: {
ctrlFunc: '='
},
See working plunkr
I'm not sure you need bindToController...
This version calls your Ctrl's function: http://plnkr.co/edit/Rxu5ZmmUAU8p63hR2Qge?p=preview
JS
angular.module('plunker', [])
.controller('Ctrl', function($scope) {
$scope.func = function() {
console.log('In the controller function');
};
}) angular.module('plunker', [])
.controller('Ctrl', function($scope) {
$scope.func = function() {
console.log('In the controller function');
};
})
.directive('myDirective', [ function() {
return {
template: '<pre>[clickme]</pre>',
replace: true,
restrict: 'E',
scope: {
target: '&'
},
link: function (scope, elem, attrs) {
elem.bind('click', function () {
var fn = scope.target && scope.target(scope);
fn && fn();
});
elem.addClass('fa fa-file-excel-o fa-lg');
}
};
}])
HTML
<div ng-controller="Ctrl">
<my-directive target="func"></my-directive>
</div>
I've created a directive that loads a template,
app.directive('youtubeTrailer', function() {
return {
restrict: 'E',
scope: {
show: '=info'
},
link: function(scope, element, attrs) {
scope.hideModal = function() {
scope.show = false;
};
},
templateUrl: '../assets/angular-app/templates/_container-trailer.html',
};
});
This is the ng-click action,
%a{"ng-click" => "toggleModal()"}
Trailer {{$index+1}}
That calls this function,
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
And then the directive gets shown,
%youtube-trailer{:info => "modalShown", :show => "modalShown"}
This works fine, but my problem is that the template is shown in the inline code. I would like to retrieve it only when the toggleModal() function has been clicked.
angular.module('test', [])
.directive('customDirective', ['$http', '$templateCache', '$compile', function($http, $templateCache, $compile) {
function getTemplate() {
return '<div>Hello, {{ name }}!</div>';
};
return {
restrict: 'A',
link : function(scope, element, attrs, fn) {
// instead of that you need to load and cache real template via $http
var template = getTemplate();
scope.name = 'world';
element.replaceWith($compile(template)(scope));
}
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div custom-directive></div>
</div>
You just need to use Angular $http service and load your file manually inside this event handler.
After that you need to compile it and insert to your directive element:
element.replaceWith($compile(template)(scope));
You also can use { cache: $templateCache } setting with $http to cache loaded template when loaded once.
Example: (inside directive)
// you need to have injected following dependencies here:
// $http, $compile, $templateCache
link: function(scope, element, attrs, fn) {
//...
scope.onSomeClick = function() {
$http.get(templateUrl, { cache: $templateCache })
.then(function(template) {
element.replaceWith($compile(template)(scope));
});
};
//...
}