Angular toggle class to parent element - angularjs

For angular I'm using a Directive to Toggle Class:
app.directive('toggleClass', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('click', function() {
element.toggleClass(attrs.toggleClass);
});
}
};
});
And the HTML I have multiple times:
<div class="tab" toggle-class="open">
<div class="title">
<p>Tab title</p>
</div>
<div class="content">
<!-- This element hidden by default, needs toggle -->
<p>Foobar</p>
</div>
</div>
It works, but when I click somewhere in the .content-element, it also toggles. But I want it to stay active. Not toggle-ing back to the close-state.
Is there an easy way to let it work like this:
- click on .title
- toggle .content (by adding .open to the .tab-element.

Added .parent()
app.directive('toggleClass', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('click', function() {
element.parent().toggleClass(attrs.toggleClass);
});
}
};
});
And toggle-class to the title element.
<div class="tab">
<div class="title" toggle-class="open">
<p>Tab title</p>
</div>
<div class="content">
<!-- This element hidden by default, needs toggle -->
<p>Foobar</p>
</div>
</div>

I just consider that you don't need a custom directive to do this kind of things.
Here is two exemples, first one with the angular way to toggleClass, second one in a global angular way.
Both will meet your needs covered by this directive.
First One :
<div ng-repeat="aTab in [{},{},{},{},{}]" class="tab" ng-class="{'open':isOpen}">
<div class="title" ng-click="isOpen = !isOpen">
<p>Tab title</p>
</div>
<div class="content">
<!-- This element hidden by default, needs toggle -->
<p>Foobar</p>
</div>
</div>
with this CSS
.content {
display:none;
}
.open .content {
display:block;
}
Second one :
<div ng-repeat="aTab in [{},{},{},{},{}]" class="tab">
<div class="title" ng-click="aTab.show = !aTab.show">
<p>Tab title</p>
</div>
<div class="content2" ng-show="aTab.show">
<!-- This element hidden by default, needs toggle -->
<p>Foobar</p>
</div>
</div>
You can see theses exemples in this plunker
Hope it helped
EDIT : Updated the exemples and plunker to show how it works with an ng-repeat

Related

Automatic scrolling with angularJs

I have a list of items, inside a div, with a ng-repeat angular directive. And I need this list, to use an automatic scrolling, it's a DEMO (it's, use the jquery super-treadmill). How can I do this with angular js (version 1.6)?
<div class="panel-body">
<div ng-repeat="model in collection">
<h1>{{model.name}}</h1>
<p>{{model.description}}</p>
</div>
</div>
you can do it with simple directive
app.directive('startTreadmill', function(){
return {
link: function(scope, element, attr){
$(element).startTreadmill({ direction: "down"});
}
}
})
<div class="panel-body" start-treadmill>
<div ng-repeat="model in collection">
<h1>{{model.name}}</h1>
<p>{{model.description}}</p>
</div>
</div>

AngularJS Wrapper Html

I am using same divs in my view but inside of divs are changing.So I want to make it in a directive. What is the way for this?
Example;
<div id="firstDiv">
<div id="secondDiv">
<div id="thirdDiv">
<label....>
</div>
</div>
</div>
<div id="firstDiv">
<div id="secondDiv">
<div id="thirdDiv">
<select....>
</div>
</div>
</div>
<div id="firstDiv">
<div id="secondDiv">
<div id="thirdDiv">
<textArea....>
</div>
</div>
</div>
So i want to make this part as a directive ;
<div id="firstDiv">
<div id="secondDiv">
<div id="thirdDiv">
</div>
</div>
</div>
Can you help ?
Use this:
<my-wrapper>
Your content here
</my-wrapper>
And script (UPDATED: Load html file instead inline html):
module.directive('myWrapper', function ($http, $compile) {
var linker = function (scope, element, attrs) {
$http.get('wrapper.html').success(function (data) {
element.replaceWith($compile(data)(scope));
});
};
return {
restrict: 'E',
link: linker
};
});
JSFiddle

Angularjs change view template after link clicked

I am trying to change html template after link is clicked. Value is boolean, initial value is true and appropriate template is loaded, but when value changed to false new template is not loaded, I don't know the reason. When initial value of boolean is true other template is loaded successfully, but on method called not. Please, help.
Here is my code:
TaskCtrl
app.controller('TasksCtrl', ['$scope', 'TaskService', function ($scope, TaskService) {
// initialize function
var that = this;
that.newTask = true;
that.name = "My name is Nedim";
that.templates = {
new: "views/task/addTask.html",
view: "views/task/viewTask.html"
};
// load all available tasks
TaskService.loadAllTasks().then(function (data) {
that.items = data.tasks;
});
$scope.$on('newTaskAdded', function(event, data){
that.items.concat(data.data);
});
that.changeTaskView = function(){
that.newTask = false;
console.log("New task value: " + that.newTask);
};
return $scope.TasksCtrl = this;
}]);
task.html
<!-- Directive showing list of available tasks -->
<div class="container-fluid">
<div class="row">
<div class="col-sm-6">
<entity-task-list items="taskCtrl.items" openItem="taskCtrl.changeTaskView()"></entity-task-list>
</div>
<div class="col-sm-6" ng-controller="TaskDetailCtrl as taskDetailCtrl">
<!-- form for adding new task -->
<div ng-if="taskCtrl.newTask" ng-include="taskCtrl.templates.new"></div>
<!-- container for displaying existing tasks -->
<div ng-if="!taskCtrl.newTask" ng-include="taskCtrl.templates.view"></div>
</div>
</div>
entityList directive
app.directive('entityTaskList', function () {
return {
restrict: 'E',
templateUrl: 'views/task/taskList.html',
scope: {
items: '='
},
bindToController: true,
controller: 'TasksCtrl as taskCtrl',
link: function (scope, element, attrs) {
}
};
});
directive template
<ul class="list-group">
<li ng-repeat="item in taskCtrl.items" class="list-group-item">
<a ng-click="taskCtrl.changeTaskView()">
<span class="glyphicon glyphicon-list-alt" aria-hidden="true"> </span>
<span>{{item.name}}</span>
<span class="task-description">{{item.description}}</span>
</a>
</li>
{{taskCtrl.newTask}}
Without any plunker or JSFiddle I can't tell for sure, but it might be issue with ng-if. I'm thinking of two workarounds.
First that I think is better. Use only 1 ng-include and only change the template.
HTML:
<entity-task-list items="taskCtrl.items" openItem="taskCtrl.changeTaskView('view')"></entity-task-list>
...
<div ng-include="taskCtrl.currentTemplate"></div>
JS:
that.currentTemplate = that.templates.new;
...
that.changeTaskView = function(template) {
that.currentTemplate = that.templates[template];
};
Or if you don't like this solution, try with ng-show instead of ng-if. With ng-show the elements will be rendered with display: none; property when the page loads, while with ng-if they will be rendered when the passed value is true.
Hope this helps you.

Wrap content using directive and transclude

I would like to surround and input with a wrapper which contains multiple divs. I would want the input to be placed inside of the div called "my-content". I'm using a directive to achieve this, but it's not being placed inside the wrapper.
These are the templates I tried:
This doesn't work
<div class="wrapper" >
<div class="left-side" > </div>
<div class="middle">
<div class="top-side"> </div>
<div class="my-content" ng-transclude ></div>
<div class="bottom-side"> </div>
</div>
<div class="right-side"> </div>
</div>
But this works
<div class="wrapper" >
<div class="left-side" > </div>
<div class="middle">
<div class="top-side"> </div>
<input class="my-content" ng-transclude />
<div class="bottom-side"> </div>
</div>
<div class="right-side"> </div>
</div>
Directive is defined as such:
app.directive('wrapMe', function(){
return {
restrict: "A",
templateUrl: 'template.html',
transclude: true,
replace: true
};
});
So to reiterate, I would like whatever has the wrap-me directive to be placed inside the div with 'my-content' class and ng-transclude. Am I missing something here?
Plunker link: http://plnkr.co/edit/oQtWNCBBuc61bRwzDjHP?p=preview
You're almost there. Just change transclude option to element and you're done. Basically you want both the input element and its contents to be transcluded. The previous option (transclude: true) only transcludes the contents, which is empty, that's why it didn't work.
app.directive('wrapMe', function(){
return {
restrict: "A",
templateUrl: 'template.html',
transclude: 'element',
replace: true
};
});
Updated plunkr: http://plnkr.co/edit/IX0ELKR4wKOPtt2vO6FB?p=preview

AngularJS directive binding issue

I have created an AngularJS directive on one of the pages and it's not rendering. I don't get any errors either. Following is the directive template and directive binding code. Appreciate if someone can help.
directive.js
var cardCollapsiblePanelModule = angular.module('cardCollapsiblePanelModule',[]);
cardCollapsiblePanelModule.directive('cardCollapsiblePanel', function() {
return {
restrict: 'A',
templateUrl: 'scripts/virtualserver/virtualserverfeatures/monitoringprobes/views/directive- templates/monitoring-probe-card-collapsible-panel-template.html',
scope: {
cardName: '#cardName'
},
controller: function ($scope, $element, $attrs) {
// update dependent scope.
},
link: function (scope, $element, $attrs) {}
}
});
directive HTML:
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title clearfix" data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
<div class="pull-left">{{ cardName }}</div>
<div class="pull-right" ><span class="iconSmall iconExpand"></span></div>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse">
<div class="panel-body">
<!-- load the capture card settings directive here -->
</div>
</div>
</div>
directive is being used as follows:
<div class="panel-group" id="accordion">
<!-- accordion directive for collapsible panel -->
<div card-collapsible-panel card-index="{{$index}}" ng-repeat="card in monitoringProbeCards">
</div>
</div>
My objective is to bind the headers of collapsible panels with the card name through the directive. Can someone point out what's wrong with the code?
My REST service response is as follows:
[{"id":1,"cardName":"Card 0 : PIST-16-TDM-PCI-Basic-32 - SN: GPER190201064","interfaceType":"TDM","probeServerId":2},{"id":2,"cardName":"Card 1 : PIST-16-TDM-PCI-Basic-32 - SN: GPER190201065","interfaceType":"TDM","probeServerId":2}]
Try this...
<div class="panel-group" id="accordion">
<!-- accordion directive for collapsible panel -->
<div ng-repeat="card in monitoringProbeCards">
<div card-collapsible-panel="{{$index}}"></div>
</div>
</div>
I think you need to add card-name to the directive Div:
<div card-collapsible-panel card-index="{{$index}}" ng-repeat="card in monitoringProbeCards" card-name="{{card.cardName}}" >
Binding to {{cardName}} from the directive HTML, binds to the cardName field on the isolated scope which in turn via the # sign followed by cardName binds to the card-name attribute on the directive using one-way data binding which means that the value of that attribute needs to be evaluated by Angular, hence the {{card.cardName}}.

Resources