Dynamic src with include-replace - angularjs

I used this solution to replace root node with template and it was ok. But then it was necessary to change template url dynamically. In this case previous template remains on page and new template adds after it on template url changing. Is it possible to avoid this behavior somehow? I still need to replace root element because of makeup troubles.
angular.module("app", [])
.directive('includeReplace', function() {
return {
require: 'ngInclude',
restrict: 'A',
link: function(scope, el, attrs) {
el.replaceWith(el.children());
}
};
})
.controller("MainController", function() {
this.tpl = "tpl1.html";
this.toggle_tpl = function() {
this.tpl = (this.tpl == 'tpl1.html') ? 'tpl2.html' : 'tpl1.html';
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainController as mCtrl">
<script type="text/ng-template" id="tpl1.html">
<div>First template</div>
</script>
<script type="text/ng-template" id="tpl2.html">
<div>Second template</div>
</script>
<button ng-click="mCtrl.toggle_tpl()">toggle</button>
<div ng-include="mCtrl.tpl" include-replace>
</div>
</div>
</div>

Try .html() instead of .replaceWith()
angular.module("app", [])
.directive('includeReplace', function() {
return {
require: 'ngInclude',
restrict: 'A',
link: function(scope, el, attrs) {
el.html(el.children().html()); // My changes in the line
}
};
})
.controller("MainController", function() {
this.tpl = "tpl1.html";
this.toggle_tpl = function() {
this.tpl = (this.tpl == 'tpl1.html') ? 'tpl2.html' : 'tpl1.html';
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainController as mCtrl">
<script type="text/ng-template" id="tpl1.html">
<div>First template</div>
</script>
<script type="text/ng-template" id="tpl2.html">
<div>Second template</div>
</script>
<button ng-click="mCtrl.toggle_tpl()">toggle</button>
<div ng-include="mCtrl.tpl" include-replace>
</div>
</div>
</div>

Related

I am facing problem in this code of custom directive

I am written this code for angularjs custom directive, but not geeting the output. Please help me.strong text
<html>
<head>
<title>Directives</title>
<script src="https://code.angularjs.org/1.6.9/angular.js"></script>
<script src="angular-1.7.6\angular.js"></script>
<script src="angular-1.7.6\angular.min.js"></script>
<script>
var app=angular.module("arrayApp", [])
app.controller("arrayCtrl", function ($scope) {
$scope.colors = ["RED","GREEN","BLUE","YELLOW" ];
});
app.directive('mycolor', function() {
return {
restrict: 'E',
transclude: 'true',
template: '<span ng-transclude></span>',
link: function(scope, element, attr){
element.append("<strong>"+attr.title+"</strong>");
}
};
});
</script>
</head>
<body ng-app="arrayApp">
<div ng-controller="arrayCtrl">
<div ng-repeat="c in colors">
<my-c title="{{c}}">
BASIC COLOR:
</my-c>
</div>
</div>
</body>
</html>
Iam not getting where I am wrong.
I am getting the output as
Output
The code is as below :
<html>
<head>
<title>Directives</title>
<script src="https://code.angularjs.org/1.6.9/angular.js"></script>
<script>
var app=angular.module("arrayApp", [])
app.controller("arrayCtrl", function ($scope) {
$scope.colors = ["RED","GREEN","BLUE","YELLOW" ];
});
app.directive('mycolor', function() {
return {
restrict: 'E',
transclude: 'true',
template: '<span ng-transclude></span>',
link: function(scope, element, attr){
element.append("<strong>"+attr.title+"</strong>");
}
};
});
</script>
</head>
<body ng-app="arrayApp">
<div ng-controller="arrayCtrl">
<div ng-repeat="c in colors">
<mycolor title="{{c}}">
BASIC COLOR:
</mycolor>
</div>
</div>
</body>
</html>
Firstly change the name of the directive into camelCase, it's a good convention for naming directives. So your directive name should be myColor.
Then use the directive like - my-color. Below is the whole code -
<html>
<head>
<title>Directives</title>
<script src="https://code.angularjs.org/1.6.9/angular.js"></script>
<script>
var app=angular.module("arrayApp", [])
app.controller("arrayCtrl", function ($scope) {
$scope.colors = ["RED","GREEN","BLUE","YELLOW" ];
});
app.directive('myColor', function() {
return {
restrict: 'E',
transclude: 'true',
template: '<span ng-transclude></span>',
link: function(scope, element, attr){
element.append("<strong>"+attr.title+"</strong>");
}
};
});
</script>
</head>
<body ng-app="arrayApp">
<div ng-controller="arrayCtrl">
<div ng-repeat="c in colors">
<my-color title="{{c}}">
BASIC COLOR:
</my-color>
</div>
</div>
</body>
</html>
This is the output -

Unable to change the Parent Scope variable from Directive scope using two way binding

I am trying to create a custom directive which takes a username as an input. It then validates and checks if the username is available or not. If the username is not available I want to pass some values back to the parent Controller.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>AngularJS Isolate Scope</title>
</head>
<body>
<div ng-app="mainApp">
<div ng-controller="AppCtrl">
<div> From Controller : <input type="text" ng-model="ctrlRole"></div><br>
{{parentVariable}}
<input type="text" is-unique="{url: 'http://WWW.GOOGLE.COM'}" ng-model="role"/>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
var app = angular.module('mainApp', []);
app.controller("AppCtrl", function($scope){
$scope.ctrlRole = "Development";
$scope.parentVariable = "a";
});
app.directive("isUnique", function() {
return {
restrict : 'A',
require : 'ngModel',
transclude: 'true',
scope:{
parentVariable:"="
},
link : function(scope, element, attrs, ngModel) {
element.bind('blur', function (e) {
if (!ngModel || !element.val()) return;
var keyProperty = scope.$eval(attrs.isUnique);
console.log('this is the keyProperty we have received from the front end ' + keyProperty.url);
var currentValue = element.val();
console.log('this is the data we are going to validate ' + currentValue);
if(currentValue == 'AE'){
console.log('Changing the value ');
scope.parentVariable = 'b';
}
});
}
}
});
</script>
</body>
In summary I am trying to change the value of parentVariable from the directive scope depending on some conditions but its not happening, please let me know what I am doing wrong.
You specify the isolate scope parameter parentVariable, but in the template there is no value passed to it:
<input type="text" is-unique="{url: 'http://WWW.GOOGLE.COM'}" ng-model="role"/>
You would need:
<input type="text" is-unique="{url: 'http://WWW.GOOGLE.COM'}" parent-variable="parentVariable" ng-model="role"/>
Here, is an isolated example.
var app = angular.module('test', []);
app.controller('MainCtrl', function($scope) {
$scope.foo = 'foo';
});
app.directive('testDir', function($timeout) {
return {
restrict: 'A',
scope: {
val: '='
},
link: function(scope) {
console.log(scope.val);
$timeout(function() {
scope.val = 'bar';
}, 1000);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="MainCtrl">
{{foo}}
<div test-dir val="foo"></div>
</div>
</div>

How to use the directive with the button click in AngularJS?

I have directive named openDialog as follows. How can I use it from the view with the button click? Here is my code for the directive
app.directive('openDialog', ['ngDialog', function (ngDialog) {
return {
restrict: 'A',
link: function ($scope, $element, $attrs) {
var openDialog = function () {
ngDialog.open({
//template: $attrs.openDialog,
template: 'src/app/reservation/addReview.html',
//ngDialog.open({ template: 'src/app/reservation/addReview.html'}),
scope: $scope,
showClose: false,
closeByEscape:true
});
};
$element.on('click', openDialog);
}
};
}]);
Try like this,
<div ng-controller="ctrl">
<mydirc></mydirc>
<button ng-click="clickMe()">call clickMe()</button>
</div>
app.directive('mydirc', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
$scope.clickMe= function() {
alert('inside click');
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
Your Code is right.
var app = angular.module('temp',['ngDialog']);
app.controller('mainCtrl', function($scope,$http,ngDialog){
$scope.label = "ME ANGULAR, gaga!"
});
app.directive('openDialog', ['ngDialog', function (ngDialog) {
return {
restrict: 'A',
link: function ($scope, $element, $attrs) {
var openDialog = function () {
ngDialog.open({
template: 'firstDialog',
scope: $scope,
showClose: false,
closeByEscape:true
});
};
$element.on('click', openDialog);
}
};
}]);
<!doctype html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Example - example-ng-keypress-production</title>
<link rel="stylesheet" type="text/css" href="//likeastore.github.io/ngDialog/css/ngDialog.css">
<link rel="stylesheet" type="text/css" href="//likeastore.github.io/ngDialog/css/ngDialog-theme-default.css">
<link rel="stylesheet" type="text/css" href="//likeastore.github.io/ngDialog/css/ngDialog-theme-flat.css">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="//likeastore.github.io/ngDialog/js/ngDialog.min.js"></script>
</head>
<body ng-app="temp">
<div ng-controller="mainCtrl">
<label>{{label}}</label>
<br/>
<button open-Dialog>Clickme</button>
</div>
</body>
<script type="text/ng-template" id="firstDialog">
<div class="ngdialog-message">
<h1>Hello</h1><i>I'm ufa, you loaded me</i>
</div>
</script>
</html>

ng-hide breaking my directive in angular 1.3.16

I'm trying to migrate from angular 1.2.28 to angular 1.3.16, however my code broke.
Angular 1.2.28 working: http://plnkr.co/edit/XfVakwA3Upm7Z2wosHCQ?p=preview
Angular 1.3.16 not working: http://plnkr.co/edit/4VxcHL0MHddobkmu9DMG?p=preview
JS
var app = angular.module('app', []);
app.run(function($rootScope, $timeout){
$rootScope.loading = true;
$timeout(function(){
$rootScope.items = ['Angular', '1.3.16', 'doesnt work'];
$rootScope.loading = false;
}, 3000);
});
app.directive('refresh', function(){
return {
restrict: 'A',
require: '^myDirective',
link: function(scope, element, attrs, ctrl){
if(scope.$last)
ctrl.init();
}
};
});
app.directive('myDirective', function(){
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<div class="my-directive"><p>Height: {{myHeight}}</p> <div ng-transclude></div></div>',
controller: function($scope, $element){
this.init = init;
function init(){
$scope.myHeight = $('.my-directive').height();
}
}
};
});
HTML
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.3.16" data-semver="1.3.16" src="https://code.angularjs.org/1.3.16/angular.js"></script>
<script data-require="jquery#1.11.0" data-semver="1.11.0" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Angular 1.3.16</h1>
<div ng-show="loading">Loading...</div>
<my-directive ng-hide="loading">
<div ng-repeat="item in items" refresh>
<p>{{item}}</p>
</div>
</my-directive>
</body>
</html>
The idea is to only run certain code when the inner html is outputted.
Height is 0 in angular 1.3.16.
However, if I remove ng-hide="loading" from <my-directive ng-hide="loading"> in angular 1.3.16, height gets the appropriated value.
Any ideas how can I solve this?
Inject $timeout into your directive and put the init code block in $timeout(function(){ ... }) like this:
app.directive('myDirective', function($timeout){
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<div class="my-directive"><p><b>Height: {{myHeight}}</b></p> <div ng-transclude></div></div>',
controller: function($scope, $element){
this.init = init;
function init(){
$timeout(function(){
$scope.myHeight = $('.my-directive').height();
});
}
}
};
});
var app = angular.module('app', []);
app.run(function($rootScope, $timeout) {
$rootScope.loading = true;
$timeout(function() {
$rootScope.items = ['Angular', '1.3.16', ' work'];
$rootScope.loading = false;
}, 1000);
});
app.directive('myDirective', function($timeout) {
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<div class="my-directive"><p>Height: {{myHeight}}</p> <div ng-transclude></div></div>',
link: function($scope, $element) {
$element.on('DOMAttrModified DOMSubtreeModified', init);
function init() {
$scope.$apply(function() {
$scope.myHeight = $element.height();
});
}
}
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="jquery#1.11.0" data-semver="1.11.0" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script data-require="angular.js#1.3.16" data-semver="1.3.16" src="https://code.angularjs.org/1.3.16/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Angular 1.3.16</h1>
<div ng-show="loading">Loading...</div>
<my-directive ng-hide="loading">
<div ng-repeat="item in items" refresh>
<p>{{item}}</p>
</div>
</my-directive>
</body>
</html>
You have to set the height in the correct angular directive phase/lifecycle. You should set the hight in the link or even postlink phase. Usually the two phases are the same if you don't use prelink This is when all the content has already been rendered. See angular $compile or google for angular post link
The controller is for the logic and the link is for html/dom manipulations.
EDIT:
You can bind 'DOMAttrModified DOMSubtreeModified` events to trigger changes.

how to call the directive on button click inside custom directive

Hi i am working on custom directives of angularjs. I just want to know that how to call the directive when I click the button. Please suggested me how to achieve this.
Thanks
<div ng-controller="ctrl">
<mydirc></mydirc>
<button ng-click="clickMe()">call clickMe()</button>
</div>
app.directive('mydirc', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
$scope.clickMe= function() {
alert('inside click');
}
}
}
});
The following example shows a sample custom directive which can handle click events; This is a scope-independent directive. And the appRoot module has to be defined earlier.
<div ng-controller="MyController">
<button custom-click="">Click Me</button>
</div>
appRoot.directive('customClick', function() {
return {
link: function(scope, element, attrs) {
element.click(function(){
//Do something useful
});
}
}
});
By "calling" the directive I am going to assume you mean handling the onclick event from the directive.
You can leverage the 'link' property of directives to attach scope initialization and functions like so:
http://jsbin.com/moruyoso/2
HTML
<!DOCTYPE html>
<html ng-app='app'>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div clicker></div>
</body>
</html>
JS
var app = angular.module('app', []);
app.directive('clicker', function(){
var link = function(scope){
scope.showMessage = function(){
alert('you clicked the directive!');
};
};
return{
link: link,
template: "<button ng-click='showMessage()'>Click me!</button>"
};
});
This example shows how to handle a click event for more than one button inside a directive:
Java Script: ( app.js )
angular.module('app', [])
.controller("articles.controller", function(){
var viewModel = this;
viewModel.articles =
[
{
title: "PHP",
content: "content 1",
selected: false
},
{
title: "C#",
content: "content 2",
selected: false
}
];
viewModel.addArticle = function(){
viewModel.articles.push(
{
title: "MySQL",
content: "new content",
selected: false
}
);
};
viewModel.select = function(article){
article.selected = !article.selected;
};
viewModel.getAll = function(){
console.clear();
console.log(viewModel.articles);
};
viewModel.getSelected = function(){
console.clear();
angular.forEach(viewModel.articles, function(article, key){
if(article.selected)
{
console.log(article.title);
}
});
};
})
.directive("artilceTile", function(){
return {
restrict: 'E',
scope: {
article: '='
},
link: function(scope, element, attr)
{
scope.displayTitle = function()
{
alert(scope.article.title);
},
scope.displayContent = function()
{
alert(scope.article.content);
},
scope.inverseArticleStatus = function()
{
scope.article.selected = !scope.article.selected;
}
},
template: `
<h1>{{article.title}}</h1>
<p>{{article.content}}</p>
<p ng-if="article.selected">Selected</p>
<input ng-model=article.title>
<button ng-click="displayTitle()">Dispaly Title</button>
<button ng-click="displayContent()">Display Content</button>
<button ng-click="inverseArticleStatus()" ng-if="!article.selected">Select</button>
<button ng-click="inverseArticleStatus()" ng-if="article.selected">Unselect</button>
<br><br><br><hr>
`
};
});
HTML: ( index.html )
<!DOCTYPE html>
<html ng-app="app">
<head>
<title></title>
</head>
<body>
<div ng-controller="articles.controller as articlesController">
<span ng-repeat="article in articlesController.articles">
<artilce-tile article="article"></artilce-tile>
</span>
<br><br>
<button ng-click="articlesController.addArticle()">Add New Article</button>
<button ng-click="articlesController.getSelected()">Get Selected Articles</button>
<button ng-click="articlesController.getAll()">Get All Articles</button>
</div>
<script type="text/javascript" src="angular.js"></script>
<script src="app.js"></script>
</body>
If you mean to ask how to show a directive template on button click, use a variable in the controller scope to show/hide it and update the variable on button click.
<div ng-controller="ctrl">
<mydirc ng-show="showMydirc"></mydirc>
<button ng-click="clickMe()">call clickMe()</button>
</div>
app.controller("ctrl", function($scope){
$scope.showMydirc=false;
$scope.clickMe = function(){
$scope.showMydirc = true;
}
});

Resources