How to override an external html template angular.js - javascript

I'm using this https://github.com/amitava82/angular-multiselect multiselect dropdown for my project.
In my html:
<am-multiselect class="sv-manage-multiselect-dropdown"
ng-model="nameList.name"
options="name as name.key for name in nameList"
multiple="true"
</am-multiselect>
This dropdown has a "checkall" and "uncheckall" button in the dropdown, which I WANT to remove, while keeping the functionality of the multi-select.
This is the html in the directive the guy uses:
src/multiselect.tmpl.html
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" ng-click="toggleSelect()" ng-disabled="disabled" ng-class="{'error': !valid()}">
{{header}}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>
<input class="form-control input-sm" type="text" ng-model="searchText.label" ng-keydown="keydown($event)" autofocus="autofocus" placeholder="Filter" />
</li>
<li ng-show="multiple" role="presentation" class="">
<button class="btn btn-link btn-xs" ng-click="checkAll()" type="button"><i class="glyphicon glyphicon-ok"></i> Check all</button>
<button class="btn btn-link btn-xs" ng-click="uncheckAll()" type="button"><i class="glyphicon glyphicon-remove"></i> Uncheck all</button>
</li>
<li ng-repeat="i in items | filter:searchText" ng-class="{'selected': $index === selectedIndex}">
<a ng-click="select(i); focus()">
<i class='glyphicon' ng-class="{'glyphicon-ok': i.checked, 'empty': !i.checked}"></i> {{i.label}}</a>
</li>
</ul>
</div>
I wan't to just remove/override the checkall and uncheckall buttons WITHOUT editing this library's directive. I can override the CSS in my personal file.css, but how do I override the HTML template he uses. Thanks

I see 3 ways you could do it:
Add your own template to replace this one like this (reference):
<script type="text/ng-template" id="multiselect.tmpl.html">
html template without buttons here
</script>
The potential issue with this is that you would be overriding this template everywhere it's used. But maybe you are using this in a bunch of places and that makes sense.
Add a decorator to the directive that removes the part of the template you don't want during the compile phase and allows the rest of the directive to perform as usual:
decorator('amMultiselectPopupDirective' ['$delegate', function($delegate) {
var directive = $delegate[0];
var compile = directive.compile;
directive.compile = function(tElement, tAttrs) {
var link = compile.apply(this, arguments);
if (tAttrs.disableCheckAll) {
tElement.find('li[ng-show="multiple"]').remove();
// this code could be different, but the gist is that it would remove or hide the stuff you don't want
}
return function() {
link.apply(this, arguments);
};
};
return $delegate;
}]);
The potential issue here is that you would be changing the template for this directive everywhere the directive is used. That's why in my example I made the template change conditional based on some attribute you could define, like disableCheckAll.
Use template-url attribute that is already defined for this directive and create your own template that doesn't have these buttons:
<script type="text/ng-template" id="yourowntemplate.html">
html template without buttons here
</script>
<am-multiselect ...
template-url="yourowntemplate.html">
</am-multiselect>
I would say 3 is probably the best way to do it. But 1 could work better if you wanted to override the default, and then you wouldn't have to pass in the template-url everytime you use the am-multiselect directive.
Edit: Here is a working example for 3: http://plnkr.co/edit/m0lZSHUJ8MHslqCNPnCc?p=info

Overlap his directive with your own div with class: "no-btns"
Add this css:
.no-btns .dropdown-menu li:nth-child(2) {display:none;}
Example:
<style>
.no-btns .dropdown-menu li:nth-child(2) {
display:none;
}
</style>
<div class="no-btns">
<am-multiselect class="sv-manage-multiselect-dropdown"
ng-model="nameList.name"
options="name as name.key for name in nameList"
multiple="true"
</am-multiselect>
</div>

Related

sorting bootstrap modal-body elements in Javascript/Jquery when the page loads

I am working on the fiddle in which I want to sort multiple rows (Row1 having def and Assign a Computer Section, Row2 having abc and Assign a Computer Section, etc) coming from Bootstrap Modal.
At this moment, the rows are not sorted in the modal. The HTML/Bootstrap code which I have used in order to create the modal is :
<div class="row-computerlabel form-group clearfix">
<div class="editcomputerlabel col-sm-5">abc</div>
<div class="assigncomputerlabel col-sm-5">
<div class="btn-group bootstrap-select show-tick computerlabelscomputerselector">
<button type="button" class="btn dropdown-toggle btn-default" data-toggle="dropdown" title="Assign a computer"><span class="filter-option pull-left">Assign a computer</span> <span class="bs-caret"><span class="caret"></span></span></button>
<div class="dropdown-menu open">
<ul class="dropdown-menu inner" role="menu"></ul>
</div>
<select class="computerlabelscomputerselector selectpicker" multiple="" title="Assign a computer" tabindex="-98"></select>
</div>
</div>
<div class="deletecomputerlabel col-sm-2"><button class="btn btn-link btn-delete" data-task="deletelabel" title="Delete group" type="button"><i class="fa fa-trash-o"></i></button></div>
</div>
Problem Statement:
I am wondering what plain Javascript or Jquery code I need to add above so that all the contents in the Bootstrap Modal get sorted meaning abc, def, jkl text should show up first with their assigned computers in the fiddle when the page loads.
You could use the sort function of JavaScript.
jQuery
$(document).ready(function(){
var rowComputer = $('.row-computerlabel');
rowComputer.sort(function(a,b){
var label1 = $(a).children('.editcomputerlabel').text();
var label2 = $(b).children('.editcomputerlabel').text();
return label1 >= label2;
});
rowComputer.appendTo('#computerlabeltable');
});
This piece of code is really simple. You have in the rowComputer variable all your rows.
You apply the sort function on your array and you need to specify the condition of your sorting (here it needs to be sorted alphabetically).
Finally, you append your array containing your rows in the div englobing all yours rows.
jsFiddle
Here is a jFiddle link : http://jsfiddle.net/Lqam4g2u/

How do I toggle a class in Angular

I have a button that I want to be able to toggle a class on a div to hide and show the div how would I do that in Angular?
HTML
<div id="chatsidebar">
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" id="sidebarCollapse" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
I want to add the class "active" onto the #chatsidebar div
app.component.ts
togglesideBar() {
}
Thanks
I'm answering this part of your question:
I want to add the class "active" onto the #chatsidebar div
To do it, you can use NgClass. NgClass allows you to add or remove any class to or from an element based on the given condition. Your code will looks something like this:
HTML
<div id="chatsidebar" [ngClass]="{'active': isSideBarActive}"> <!-- this ngClass will add or remove `active` class based on the `isSideBarActive` value -->
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" id="sidebarCollapse" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
Component
isSideBarActive: boolean = true; // initial value can be set to either `false` or `true`, depends on our need
togglesideBar() {
this.isSideBarActive = !this.isSideBarActive;
}
HTML
<div id="chatsidebar" *ngIf="status">
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" id="sidebarCollapse" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
app.component.ts:
status:boolean=true;
togglesideBar() {
if(this.status == true) this.status=false;
else this.status = true;
}
Demo:
https://plnkr.co/edit/fNoXWhUhMaUoeMihbGYd?p=preview
you can try below.
<div id="chatsidebar" class="{{activeClass}}"> ... </div>
and on your component define a property and set the class value on toggle function
// On Component
activeClass : string = "";
...
togglesideBar() {
this.activeClass = 'active'
}
it shall work, but may not the ideal solution.
Assuming you have a class named hide:
<div [class.hide]="hide">
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
togglesideBar() { this.hide = !this.hide; }
This will hide the element in question, while leaving it in the DOM. The other solutions using *ngIf will add and remove the element to and from the DOM. There are subtle reasons in specific cases to prefer one over the other, well described in the on-line documentation you have already read. In this case, it doesn't really matter.
The [class.className]=boolean format is just one of several ways to control classes in Angular. For instance, you could also have said:
[ngClass]="{'hide': hide}"
This is slightly more flexible because you can add/remove multiple classes at once.
Since you are using glyphicons, you are probably using Bootstrap, so you most likely already have the hide class defined.
As an aside, you rarely need IDs, and using them is pretty much of an anti-pattern in Angular.
Take a variable in your component something like
isShowChatSidebar:boolean=true;
then modify your method and html
togglesideBar() {
this.isShowChatSidebar=!this.isShowChatSidebar
}
<div id="chatsidebar" [ngClass]="{'active': isShowChatSidebar}">>
<app-chatsidebar></app-chatsidebar>
</div>

Appending rows to nested rows issue?

I'm making a table with nested row's.
The thing is that when I append a child row to a parent row all other parent rows append a child row also.
Use function:
$scope.templates=[{src:'template'}];
$scope.include = function(templateURI) {
$scope.templates.push({src:templateURI});
}
Append row:
<button class="btn btn-default btn-sm ng-scope" ng-click="include('rowInRow.html')">
<i class="glyphicon glyphicon-upload"></i>
</button>
Show template:
<div ng-repeat="template in templates">
<div ng-include="template.src">My template will be visible here</div>
</div>
Can somebody give me a hint?
I tried to do it myself but I didn't find what I need.
Try this: http://plnkr.co/edit/ZzPF7UFjKyp2tqn27cf4?p=preview
All of the projects are sharing the templates collection. Solve this by giving each project its own templates array and iterating through that.
Make the include function into:
$scope.include = function(project, templateURI) {
if (!project.templates)
project.templates = [];
project.templates.push({src:templateURI});
}
Call it like this:
<button class="btn btn-default btn-sm ng-scope" ng-click="include(project, 'rowInRow.html')">
<i class="glyphicon glyphicon-upload"></i>
</button>
Show it like this:
<div ng-repeat="template in project.templates">
<div ng-include="template.src">My template will be visible here</div>
</div>

Angular dropdown with a button not getting data

im new to angular and was struck linking dropdown selected to ng-click button
<div class="col-xs-2">
<select name="cars" ng-model="dropdown_data">
<option>email</option>
<option>phone</option>
<option>username</option>
</select>
</div>
<br />
<div class="col-xs-4">
<button type="button" class=" " data-ng-click="search_{{dropdown_data}}()">Search</button>
</div>
<script>
var ng = angular.module('myApp', []);
ng.controller('ctrl', function($scope, $http) {
$scope.search_phone = function() {
alert("phone")
}
$scope.search_email = function() {
alert("email")
}
})
</script>
this seems to be fairly simple but im not sure what im doing wrong...Im not able to show alerts depending on selected dropdown
Plunker link http://plnkr.co/edit/Iicm9tvfizXxNl3MwtZI?p=preview
any help is much appriciated...thanks in advance
There were few things that you needed in the plunkr.
Firstly you need to define on the HTML that it is in fact an Angular Application (via the ngApp attribute).
Secondly you need to define a controller for your view (via the ngController attribute).
Once you have those things in place, you need to understand what this would do
ng-click="search_{{dropdown_data}}()"
If you think about how ng-click works, it registers a function on click. This happens on the compile phase of a directive (as you can see on its sourcecode).
This means that when the directive compiles, it will register the function with the name search_{{dropdown_data}} and even though the dropdown_data will be interpolated later on when its value changes, the originally bound function won't update.
However if you had dropdown_data as an attribute or as a key to a map of functions that will work. Here an example of how you may do that:
$scope.search = {
phone: function() {
alert("phone")
},
email: function() {
alert("email")
}
};
and on the button: data-ng-click="search[dropdown_data]()"
Here a working plunkr: http://plnkr.co/edit/u4vJj2a0r1a95w64crHM?p=preview
I am also new in angular but have used same functionality without search button direct given anchor link try this if you need,
<div ng-app="myApp">
<div ng-controller="setContent">
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Subject
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li ng-repeat="a in subjects">{{a}}</li>
</ul>
</div>
var app = angular.module('myApp', []);
app.controller('setContent', function($scope, $http) {
$scope.subjects = ['Math', 'Physics', 'Chemistry', 'Hindi', 'English'];
});
});
The problem is this data-ng-click="search_{{dropdown_data}}()". Better to pass a value to the function like this:
<button type="button" data-ng-click="search(dropdown_data)">Search</button>
$scope.search = function(type) {
alert(type)
}
also dont forget ng-app and ng-controller.
see the plunker

Click button to copy text to another div with angularjs

I have a list of Items with different button with them. Plunker
Quick View:
I want something like if I click on any of the buttons, related text will be copy to the div above. Also if I click on the button again it will removed from the Div.Same for each of the buttons. [I added manually one to show how it may display ]
I am not sure how to do that in Angular. Any help will be my life saver.
<div ng-repeat="item in csTagGrp">
<ul>
<li ng-repeat="value in item.csTags">
<div class="pull-left">
<button type="button" ng-class='{active: value.active && !value.old}' class="btn btn-default btn-xs">{{value.keys}}</button>
<span>=</span>
</div>
<div class="pull-left cs-tag-item-list">
<span>{{value.tags}}</span>
</div>
</li>
</ul>
</div>
The simplest thing would be to use $scope.tags object to store selected tags and add/remove them with the scope method similar to this:
$scope.tags = {};
$scope.toggleTag = function(tag) {
if (!$scope.tags[tag]) {
$scope.tags[tag] = true;
}
else {
delete $scope.tags[tag];
}
};
Demo: http://plnkr.co/edit/FrifyCrl0yP0T8l8XO4K?p=info
You can use ng-click to put in your scope the selected value, and then display this value instead of "Win".
http://plnkr.co/edit/IzwZFtRBfSiEcHGicc9l?p=preview
<div class="myboard">
<span>{{selected.tags}}</span>
</div>
...
<button type="button" ng-click="select(value)">{{value.keys}}</button>

Categories