I have a directive like this
app.directive('pagination',function () {
//custom directive for build pagination
return {
restrict: 'E',
template:function (elem,attr) {
console.log(attr.pageCount);
return 'pagination here';
}
};
})
and its renderd in my html like this
<pagination pageCount="2" currentPage="currentPage"></pagination>
But i want to render this after an http call from my controller
$http.post('/search',searchParams).then(function (response) {
//render `pagination` from here
})
AngularJS normalizes an element's tag and attribute name to determine
which elements match which directives. We typically refer to
directives by their case-sensitive camelCase normalized name (e.g.
ngModel). However, since HTML is case-insensitive, we refer to
directives in the DOM by lower-case forms, typically using
dash-delimited attributes on DOM elements (e.g. ng-model).
Try with ng-if..
<pagination page-count="2" current-page="currentPage" ng-if="showPage"></pagination>
$http.post('/search',searchParams).then(function (response) {
//render `pagination` from here
$scope.showPage = true;
})
(function(angular) {
'use strict';
angular.module('docsTransclusionExample', [])
.controller('Controller', ['$scope', function($scope) {
$scope.name = 'Tobias';
}])
.directive('pagination',function () {
//custom directive for build pagination
return {
restrict: 'E',
template:function (elem, attr) {
console.log(attr.pageCount);
// console.log(attr.pagecount);
return 'pagination here';
}
};
});
})(window.angular);
/*
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-directive-transclusion-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="docsTransclusionExample">
<div ng-controller="Controller" ng-init="hid = false">{{hid}}
<pagination ng-if="hid" page-count="2" current-page="currentPage"></pagination>
<button ng-click="hid=true">Click!</button>
</div>
</body>
</html>
Related
I binded html data from angular js post to Html div, but not ng click is fired in the binding html content.
This is my binding html div.
<div ng-app="SupportManagement">
<div ng-controller="SupportCtrl">
<div ng-click="openModal(5)"></div>
<div id="detailBlock"></div>
</div>
</div>
This my bind function with Angularjs Post
angular.module("SupportManagement", [])
.controller("SupportCtrl", function ($scope, $http) {
$scope.openModal = function (ticketId) {
$http.get('SupportDetail.aspx?ticketId='+ticketId).then(function (response) {
$("#detailBlock").html(response.data);
},
function (error) {
alert("fail");
alert(error);
}
);
}
$scope.openTicketHistory=function(){
var id= $('#tckId').attr('prob');
$http.post('SupportDetail.aspx/ShowHistory',
{ ticketId: id }).then(function (success) {
alert("success")
}
);
}
});
The place is I call the openTicketHistory function inside detailBlock div. And not firing the ngClick event. What can I do?
Check This Out
<html lang="en" >
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Angular Material style sheet -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.8/angular-material.min.css">
</head>
<body ng-app="BlankApp" ng-cloak>
<div>
<div ng-controller="SupportCtrl">
<div id="detailBlock">{{myWelcome}}</div>
<md-button ng-click="openModal(5)">Test</md-button>
</div>
</div>
<!-- Angular Material requires Angular.js Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-messages.min.js"></script>
<!-- Angular Material Library -->
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.8/angular-material.min.js"></script>
<!-- Your application bootstrap -->
<script type="text/javascript">
/**
* You must include the dependency on 'ngMaterial'
*/
angular.module('BlankApp', ['ngMaterial', 'ngMessages'])
.controller("SupportCtrl", function ($scope, $http) {
$scope.openModal = function (ticketId) {
$http.get('SupportDetail.aspx?ticketId='+ticketId)
.then(function (response) {
$("#detailBlock").html(response.data);
},
function (error) {
alert("fail");
alert(error);
}
);
}
$scope.openTicketHistory=function(){
var id= $('#tckId').attr('prob');
$http.post('SupportDetail.aspx/ShowHistory',
{ ticketId: id }).then(function (success) {
alert("success")
});
}
});
</script>
</body>
</html>
<!--
Copyright 2016-2018 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that can be found in the LICENSE file at https://material.angularjs.org/latest/license.
-->
First, here are some best practices
You should not access the DOM from your controller, don't try to think like Jquery where you have to access the DOM element in order to update it (See conceptual overview chapter from angularjs docs)
Avoid using $scope in your controller, use "controller as syntax instead"
Avoid using $http inside your controller, use an angularjs service instead
As for the solution, you can just use Angularjs's Data binding feature to bind the model (inside the Controller) to the view
$scope.ticket = response.data
in the view:
<div id="detailBlock">{{ticket}}</div>
Here is the link to a working jsfiddle : http://jsfiddle.net/bhjd4kto/25/
EDIT :
if your goal is to display html content inside #detailBlock, you can use angular-sanitize and ng-bind-html directive, here is an example : http://jsfiddle.net/bhjd4kto/45/
Directive code:
.directive('replace', function($compile) {
return function (scope, element) {
element.html(element.html().replace("Hej", "Hey!"));
$compile(element.contents())(scope);
}
});
})
HTML
<div ng-controller="GreeterController">
<div replace>Hej <div ng-repeat="e in arr">{{ e }}</div>
</div>
</div>
Controller
app.controller('GreeterController', ['$scope', function($scope) {
$scope.arr = [1, 2, 3, 4];
}]);
Live example
As the title says, ng-repeat doesn't work when I'm using the directive from above on HTML which contains it.
But once I remove that line which uses .replace() command to replace part of HTML then ng-repeat starts working for some reason.
Does anyone know where's the actual problem?
I have tried everything and I still seem to not get it why it doesn't work as it should.
The manipulation can also be done in the compile phase:
app.directive("replace", function(){
return {
compile: function(element){
element.html(element.html().replace('Hej', 'Hey!'));
/*return {
pre: function(scope, element){
element.html(element.html().replace('Hej', 'Hey!'));
}
}*/
}
};
});
The original problem was caused because the linking of the ng-repeat directive was done before the element with that directive is replaced with the replace operation. The watchers associated with the ng-repeat directive then operate on elements that are no longer attached to the visible DOM.
By moving the replace operation to either the compile phase or the preLink phase, the replacing of the element that has the ng-repeat directive is done before the ng-repeat directive is linked. The watchers associated with ng-repeat directive then work with the replaced DOM.
You should let Angular and its change detection cycle do the HTML manipulation for you, instead of directly changing it yourself.
I've edited your example to use scope bindings to achieve what you wanted:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-compile-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
</head>
<body ng-app="compileExample">
<script>
angular.module('compileExample', [], function($compileProvider) {
// configure new 'compile' directive by passing a directive
// factory function. The factory function injects the '$compile'
$compileProvider.directive('replace', function($compile) {
return {
link: function (scope, element) {
scope.greeting = 'Hey!';
$compile(element.contents())(scope);
}
}
});
})
.controller('GreeterController', ['$scope', function($scope) {
$scope.test = [1, 2, 3, 4];
$scope.greeting = 'Hej';
}]);
</script>
<div ng-controller="GreeterController">
<div replace>{{greeting}} <div ng-repeat="e in test">{{ e }}</div></div>
</div>
</body>
</html>
<!--
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
Note: I removed "scope: false" as that is the default behaviour.
EDIT:
Since you must replace HTML in place here's a solution with jQuery:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-compile-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
</head>
<body ng-app="compileExample">
<script>
angular.module('compileExample', [], function($compileProvider) {
// configure new 'compile' directive by passing a directive
// factory function. The factory function injects the '$compile'
$compileProvider.directive('replace', function($compile) {
return function (scope, element) {
$(element).find( ".translation" ).replaceWith("Hey!");
}
});
})
.controller('GreeterController', ['$scope', function($scope) {
$scope.arr = [1, 2, 3, 4];
}]);
</script>
<div ng-controller="GreeterController">
<div replace><span class="translation">Hej</span> <div ng-repeat="e in arr">{{ e }}</div></div>
</div>
</body>
</html>
<!--
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
Solved it like this:
.directive("replace", function(){
return {
compile: function(){
return {
pre: function(scope, element){
element.html(element.html().replace('Hej', 'Hey!'));
}
}
}
};
});
Live example
i'm trying to include directives in my application, but even basic directives aren't rendering. what am i doing wrong?
angularloader.js:
var main = angular.module('ngMain', [])
.directive('myScrollable', function () {
return {
restrict: 'AE',
template: '<h3>Hello World!!</h3>'
};
});
My HTML:
<html ng-app dir="auto">
<head>
<meta name="viewport" content="width=device-width" />
<title>#Model.Title</title>
<script src="/Scripts/Libs/angular.js"></script>
<script src="/Scripts/Custom/angularloader.js"></script>
</head>
<body dir="auto">
<my-scrollable></my-scrollable>
</body>
</html>
tried also using tag or attribute ..
you should use module name in ng-app="moduleName"
like:
<html ng-app="ngMain" dir="auto">
if you assign angular module in a variable then use that variable like bellow:
var main = angular.module('ngMain', []);
main.directive('myScrollable', function () {
return {
restrict: 'AE',
template: '<h3>Hello Worlds!!</h3>'
};
});
Working PLUNKER Link
You have define your module but forget to use in html with ng-app= "you module Name". One extra thing you don't need to declare a variable main your code will work without that also.
angular
.module('myModule', [])
.directive('myDir', function{
your code
});
I'm trying to get the height of elements in a simple AngularJS app.
See below. What am I doing wrong? The height should be different as the lines wrap, but I get 20 reported back to me regardless of what I input in the "labels" array.
The following code can be executed here, otherwise see below.
http://js.do/code/49177
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<base href="/">
<title>height of element in angularjs</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular-route.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
'use strict';
var app = angular.module('heightApp', ['ngRoute', 'routing']);
app.controller('heightCtrl', ['$scope', function ($scope) {
$scope.labels = [
'Hi there, I\'m a div.',
'Me too, I\'m also a div.',
'Can you see me, because I certainly can\'t see myself. I don\'t even know my own height. Isn\'t that just crazy?'
];
}]);
angular.module('routing', []).config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'height.html',
controller: 'heightCtrl'
});
}]);
angular.module('heightApp').directive('reportMyHeight', function() {
return function (scope, el, attrs) {
alert('offsetHeight = ' + el[0].offsetHeight);
}
})
</script>
</head>
<body ng-app="heightApp">
<div class="container">
<div ng-view></div>
</div>
</body>
<script type="text/ng-template" id="height.html">
<div class="row">
<div class="col-sm-4" report-my-height ng-repeat="lbl in labels">
{{ ::lbl }}
</div>
</div>
</script>
</html>
You need to wait till the next digest cycle. When you do it right away in the directive the interpolations {{ ::lbl }} inside the ng-repeat would not have expanded yet. You can place it in a $timeout turning off the applyDigest argument.
i.e, example:
angular.module('heightApp').directive('reportMyHeight', function($timeout) {
return function (scope, el, attrs) {
$timeout(init, false);
//Initialization
function init(){
console.log('offsetHeight = ' + el[0].offsetHeight, el.html());
}
}
});
Plnkr
Another way to make sure you get the height of the element is to use watch.
angular.module('heightApp').directive('reportMyHeight', function($timeout) {
return function (scope, el, attrs) {
scope.$watch('lbl', function(newval, oldval){
alert(newval + '\n\n' + 'offsetHeight = ' + el[0].offsetHeight);
});
}
})
It will only be triggered once since you use ::.
How would I dynamically change the page's title tag based on my page's H1 tag in AngularJS.
I know in jQuery I could do something like:
var title = $('#content').find('h1').first().text();
if (title.length >= 1)
{
document.title = 'My Site Name | ' + (title);
}
else {
document.title = 'My Site Name';
}
What is the best way to accomplish the same thing in AngularJS?
I would rather not put it in the app.js because to me it seems wrong to be putting content -- which may change -- mixed with the code. If I edit the text of the H1 in my partial view it needs to automatically change the title.
Assuming you want to bind the title to static h1 content, you can use the following directive:
var app = angular.module('bindTitle', []);
app.directive('bindTitle', ['$document', function($document) {
return {
restrict: 'A',
link: function(scope, iElement) {
$document[0].title += ' | ' + iElement.text();
}
};
}]);
The usage will be:
<html>
<head>
<title>My Site Name</title>
<head>
<body>
<h1 bind-title>Your title</h1>
</body>
</html>
And Your title will be appended to the page title on page load. i.e. My Site Name | Your title
Edit: auto append title on h1 element
var app = angular.module('bindTitle', []);
app.directive('h1', ['$document', function($document) {
return {
restrict: 'E',
link: function(scope, iElement) {
$document[0].title += ' | ' + iElement.text();
}
};
}]);
And content inside <h1> elements will be appended to the page title.
It is there in the documentation,
Try something like this
angular.module('documentExample', [])
.controller('ExampleController', ['$scope', '$document', function($scope, $document) {
$scope.title = $document[0].title;
$scope.windowTitle = angular.element(window.document)[0].title;
}]);
http://plnkr.co/edit/rlq032m5KTVLSRMDRHvr?p=preview
You can use Angular's data binding on the <title> element with either ng-bind or ng-bind-template.
Of course, you need to have the desired value in a variable on your module/controller (e.g., $scope) to use data binding. If the value isn't part of the scope, Angular can't offer any "better" solution than jQuery or standard JavaScript (you'll need to find the <h1> tag on the page and extract the text in some fashion regardless).
angular.module('app', [])
.controller('MyCtrl', function($scope) {
$scope.title = 'My Page';
});
<html ng-app="app" ng-controller="MyCtrl">
<head>
<!-- Direct binding example -->
<title ng-bind="title"></title>
<!-- Or, template example -->
<title ng-bind-template="My Site{{ title.length > 0 ? ' | ' + title : ''}}"></title>
You can use $watch to change the title
<body ng-app="app">
<div ng-controller="demo">
<h1>{{title}}</h1>
<input type="text" ng-model="title" />
</div>
</body>
<script>
angular.module('app', []).controller('demo', ['$scope', function($scope) {
$scope.$watch($scope.title, function() {
document.title = $scope.title;
});
}]);
</script>
I think the easiest way to do this is to set same model for your title and for your h1
Take this jsFiddle link as an example. When you are writing something in that textbox, name is modified in 2 places, in the same time.
Note: You should do this in a MasterController for your Layout html page.