Override the default pagination template of ui-bootstrap - javascript

I am using AngularJS to show pagination. I made some changes on the default pagination template. This is my HTML:
<ul uib-pagination ng-model="source_pagination.current" template-url="pagination.html" total-items="source_pagination.total_pages" items-per-page="1" max-size="source_pagination.max_items" class="pagination-sm" force-ellipses="true" direction-links="false" ng-change="source_page_changed()"></ul>
...
<script id="pagination.html" type="text/ng-template">
<ul class="pagination">
<li ng-if="boundaryLinks" ng-class="{disabled: noPrevious()}">
<a href ng-click="selectPage(1)" title="First Page">
<span class="glyphicon glyphicon-fast-backward"></span>
</a>
</li>
<li ng-if="directionLinks" ng-class="{disabled: noPrevious()}">
<a href ng-click="selectPage(page - 1)" title="Previous Page">
<span class="glyphicon glyphicon-step-backward"></span>
</a>
</li>
<li ng-repeat="page in pages track by $index" ng-class="{active: page.active}">
<a href ng-click="selectPage(page.number)" ng-class="{highlight: ShouldHighlightPage(page.number)}">
{{page.text}}
</a>
</li>
<li ng-if="directionLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(page + 1)" title="Next Page"><span class="glyphicon glyphicon-step-forward"></span></a></li>
<li ng-if="boundaryLinks" ng-class="{disabled: noNext()}"><a href ng-click="$scope.changePage('last')" title="Last Page"><span class="glyphicon glyphicon-fast-forward"></span> </a></li>
</ul>
</script>
I modified this section:
<li ng-repeat="page in pages track by $index" ng-class="{active: page.active}">
<a href ng-click="selectPage(page.number)" ng-class="{highlight: ShouldHighlightPage(page.number)}">
{{page.text}}
</a>
</li>
And added this class-condition {highlight: ShouldHighlightPage(page.number)}. This code should call the function ShouldHighlightPage(pageNum) which is located in the controller:
$scope.ShouldHighlightPage = function (pageNum)
{
return true;
}
So all the pages should contain the class highlight. But this function is never called (checked by adding a breakpoint in the function). All the pages presented without the highlight class.
What am I doing wrong?
Thank you.

Okay, got the issue here.
The uib-pagination directive creates an isolated scope. See it here: https://github.com/angular-ui/bootstrap/blob/2.1.3/src/pagination/pagination.js#L126
And from the docs:
Scope
{...} (an object hash): A new "isolate" scope is created for the
directive's element. The 'isolate' scope differs from normal scope in
that it does not prototypically inherit from its parent scope. This is
useful when creating reusable components, which should not
accidentally read or modify data in the parent scope.
That means, the method ShouldHighlightPage will not be available in the scope of your overridden template.
One immediate solution (not recommended, getting you a cleaner solution) is to register your method in $rootScope:
$rootScope.ShouldHighlightPage = function (pageNum)
{
return true;
}
To fix this problem, add a custom directive:
myApp.directive('uibCustomPagination', function () {
return {
restrict: 'A',
require: 'uibPagination',
link: function ($scope, $element, $attr, uibPaginationCtrl) {
uibPaginationCtrl.ShouldHighlightPage = function (pageNum) {
return true;
};
}
}
});
This directive is basically injecting your method to the controller of uib-pagination directive so that it can be available in your template.
Now, just apply uib-custom-pagination directive to your ul element:
<ul uib-pagination uib-custom-pagination ng-model="source_pagination.current"
template-url="pagination.html" total-items="source_pagination.total_pages"
items-per-page="1" max-size="source_pagination.max_items" class="pagination-sm"
force-ellipses="true" direction-links="false" ng-change="source_page_changed()"></ul>

Related

AngularJS - get the link in HTML

Good morning, this one is the only question that is similar in nature to mine, but unfortunately, it did not help me find an answer, so your help is highly appreciated.
I have the following snippet of HTML code:
<li class="first-page" ng-click="selectFirst()" onclick="window.scrollTo(0,0)">
First
</li>
I want to adjust the <li> so that it shows a link. In the directive's link function I included one more function:
function getPaginationLink($location) {
var linkToPage = $location.$$url;
console.log($location.$$url);
return linkToPage;
}
and slightly changed the html, in the following way:
<li class="first-page" ng-click="selectFirst()" onclick="window.scrollTo(0,0)">
<a ng-onload="getPaginationLink($location)" ng-href="{{ linkToPage }}">
First
</a>
</li>
linkToPage is not linked with the model anywhere in your controller's getPaginationLink function and using it in href="{{linkToPage}}" would be undefined.
If you just want to use the returned in value of getPaginationLink in href, just use
<li class="first-page" ng-click="selectFirst()" onclick="window.scrollTo(0,0)">
<a ng-init="url = getPaginationLink($location)" ng-href="{{url}}">First</a>
</li>
Here is an example snippet
angular.module('app', []).controller('ctrl', function($scope){
$scope.getr = function(){
return "URL"
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<li class="first-page" ng-click="selectFirst()" onclick="window.scrollTo(0,0)">
<a ng-init="url = getr()" ng-href="{{url}}">First</a>
</li>
</div>

How to use ng-template in angular?

I'm writing a client-side angular app and I have a question related to the way I can use angular's ng-template.
So, I have this navbar:
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<!--<li class="active">Home</li>-->
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Events <span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Create Event</li>
<li></li>
</ul>
</li>
<li>About</li>
</ul>
<ul class="nav navbar-nav navbar-right" ng-include="getTemplate()">
</ul>
</div>
</div>
</nav>
Ok, in the last <ul> tag I use ng-include="getTemplate()", where getTemplate is this function:
<script type="text/javascript">
$(function () {
var getTemplate = function () {
return "notauth";
}
})
</script>
Basically, this will return the same template, but I just want this to work before I add more logic to it.
"notauth" template is:
<script type="text/ng-template" id="notauth">
<li><a ui-sref="signup"><span class="glyphicon glyphicon-user"></span> Sign Up</a></li>
<li><a ui-sref="login"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>
</script>
Note that this is inside my index.html page, because I want my navbar to be the same for all views, but change its template according to user state: if user is logged in use auth template, otherwise use notauth template.
Problem is that this doesn't work and I can't figure out what the problem is.
Declare the function using $scope as follows:
$scope.getTemplate = function () {
return "notauth" ;
console.log("notauth")
}
Then you can call like this:
<ul class="nav navbar-nav navbar-right" ng-include="getTemplate()">
This works correctly.
The reason why your function doesn't work is because you define your function in a function (that is automatically called by jQuery) and is thus only available in the scope of that function.
But even if you were to add the getTemplate() to the global (window) scope, it would still not work as Angular looks for it on the current $scope object.
So the only way you can make this work:
<ul class="nav navbar-nav navbar-right" ng-include="getTemplate()">
Is if you somehow get getTemplate() onto the current $scope or the $rootScope. This can be accomplished by for instance the following code:
angular.module('myApplication', [])
.run(['$rootScope', function($rootScope) {
$rootScope.getTemplate = function() {
return 'notauth';
};
}]);
Do note however that while something like this may work, you're much better of creating a component for this functionality which can then have an injectable controller that can actually perform smart logic.
ng-include="'notauth'" works like this, not ng-include="notauth"
So, try to do something like that.
<script type="text/javascript" >
angular.module('app', []).
controller('MainC', function($scope){
$scope.call = function(){
return 'notauth';
}
})
</script>

How to apply active class in navigation if i used breadcrumb in angular js

I m learning to angular js and read some documents but i have face one problum .
HI i m using a application with navigation as like this
<ul class="nav navbar-nav">
<li ui-sref-active="active"><a ui-sref="dashboard.view">Dashboard</a></li>
<li ui-sref-active="active"><a ui-sref="aboutus">About</a></li>
<li ui-sref-active="active"><a ui-sref="contactus">Contact</a></li>
</ul>
Now my brodcrome is
Home > About > Carrer
My url is myxyz.com/#/aboutus/carrer
than active class is not apply About but if i click to About page than active class is add.
Can u please tell me what I code write.
Thanks .
What I did on your case was I created a function inside a controller with couple of dependencies and then use ng-class,
storeApp.controller('MyCtrl', function($scope, $location, $http) {
$scope.isActive = function(route) {
return route === $location.path();
}
And then used it in my navigation.
<ul class="nav navbar-nav" ng-controller="MyCtrl">
<li class="hvr-underline-from-left">
<a ng-class="{activeClass:isActive('/store')}" href="#/store">SHOP</a>
</li>
<li class="hvr-underline-from-left">
<a ng-class="{activeClass:isActive('/category/0/0')}" href="#/category/0/0">COLLECTIONS</a>
</li>
</ul>
In this example, make sure you have declared activeClass or what ever class name you want in your CSS

How can I have angular-ui-router with a blank ui-sref attribute?

I'm writing a dropdown nav in bootstrap and angular with angular-ui-router. When a link has a dropdown, the link should be blank. But if I pass a blank route to ui-sref I get an error.
Here's a code snippet:
<ul class="dropdown-menu">
<li ng-repeat="button in buttons" id="foo" ng-class="{'dropdown-submenu': $index=button.hasLinks}" >
<a ui-sref="{{button.route}}" title="{{ button.text }} Tab" class="{ dropdown-toggle: button.links }" data-toggle="dropdown">
<i class="icon icon-{{ button.icon }}"></i> {{ button.text }}
</a>
<ul class="dropdown-menu">
<li ng-repeat="link in button.links">
<a ng-href="{{ link.route }}" title="{{ link.text }} Tab">
{{ link.text }}
</a>
</li>
</ul>
</li>
</ul>
Currently, as you can read in this topic, ui-sref doesn't handle empty argument, as it is (quoting the author) a misuse of the directive. Upcomming ui-state directive is supposed to handle that, but for now the best way I found was (in Angular 1.3 and above) to use ng-attr as below:
ng-attr-ui-sref="{{ state || undefined }}"
If state is blank, it will yield undefined, and no attribute in effect.
EDIT: Note that as long as it works, it will throw an exception in the console due to ui-router open bug
I solved this issue by not using ui-sref, but rather ng-href:
<a ng-href="{{ ::someObject.href }}">some link</a>
controller:
someObject.href = $state.href('FancyState', params: { id: 123 });

What's the best way to "transfer" directives from and to, using AngularJs

I have a widget that has the following structure (it's a "plan selector" resume):
<div>
<ul>
<li resume="to" ng-repeat="item in items"></li>
</ul>
<div class="total"></div>
<ul>
<li resume="from" ng-repeat="item in items"></li>
</ul>
</div>
my directive is the following:
plans.directive('resume', function() {
return {
restrict: 'A',
template: '<h3>{{step.name}}</h3><div>{{val}}</div>',
link: function($scope, element, attrs, controller) {}
};
});
Notes:
plans is an angular.module('Plans')
items is some data that is loaded via AJAX, and each item has a selected attribute
they share the same controller as the items that will be selected, that is PlansCtrl
What I want:
When the user finishes selecting the items (setting each "selected"), it will only show in the "to" when it's selected, and it will only show in the "from" when it's not selected. I don't want to hard code anything because everything is mounted using AJAX.
Assuming I'm understanding you right, it's probably better to use the filter filter like so:
http://jsfiddle.net/qbGeG/
<div ng-app ng-controller="x">
<b>selected</b>
<ul>
<li ng-repeat="item in items | filter:{selected:true}" ng-click="item.selected = !item.selected">{{item.name}}</li>
</ul>
<div class="total"></div>
<b>unselected</b>
<ul>
<li ng-repeat="item in items | filter:{selected:!true}" ng-click="item.selected = !item.selected">{{item.name}}</li>
</ul>
</div>
If you need the functionality as a directive, then it would be better to replace the entire li element with something like: <selectableList source="items" /> where your directive just uses filter and ngClick like I did above.

Categories

Resources