I'm writting a custom directive to bind a html select element to an unordered list.
It works just fine with static select elements.
However, I couldn't make it work with dynamic selects. Is there a way to my directive retrieve the options generated by ng-options or ng-repeat directives?
I have an example here: http://jsfiddle.net/fjbyq/3/
angular.module('myApp', [])
.directive('taskFilterChoices', function() {
return {
transclude: true,
replace: true,
template: '<div class="listToggleBox listType" data-ng-transclude><ul class="choicefilterList"><li data-ng-repeat="option in options"> {{ option.text }} </li> </ul> </div>',
scope: {},
link: function(scope, element, attrs) {
var _select = element.find('select'),
_selectOptions = [];
_select.hide();
_select.find('option').each(function(i, option) {
var _optionObj = {
value: option.value,
text: option.innerText
};
_selectOptions.push(_optionObj);
});
scope.options = _selectOptions;
}
};
})
.directive('taskFilterLink', function() {
return {
restrict: 'C',
link: function(scope, element) {
$(element).on('click', function(e){
e.preventDefault();
var _select = $(this).closest('.listToggleBox').find('select');
_select.val($(this).data('value')).triggerHandler('change');
});
}
};
});
Thanks
Related
I am trying to create a reusable html element / angular directive that will be used inside of ng-repeat so I want to pass it the values it will display in the DOM.
Something worth noting, I don't care for the values to bind. They can be a one-time binding simply displaying their values the first time ng-repeat creates them.
For example here is my directive:
app.directive('newsListing', function () {
return {
restrict: 'AE',
replace: 'true',
templateUrl: '../Pages/Views/Templates/newsListing.html',
scope: {},
link: function (scope, elem, attrs) {
//Fairly sure this is where the binding needs to happen?
}
};
});
My HTML template:
<div>
<span class="glyphicon glyphicon-list-alt logo-green"></span>
<label>{{DateValue}}</label>
<label>{{Category}}</label>
<label class="noBorder">{{Content}}</label>
What I want the ending product to be:
<news-Listing Date="{{someValue}}" Category="{{someValue}}" Content="{{someValue}}"></news-Listing>
I have never created a directive before and all the guides I am trying to follow don't explain the scope, and the way binding happens inside of a directive.
Try like this
var app = angular.module('anApp', []);
app.controller('aCtrl', function($scope) {
$scope.data = [{date:"2000-12-12",category:"sport",content:"this is a test"}]
});
app.directive('newsListing', function () {
return {
restrict: 'AE',
replace: 'true',
template: '<div><label>{{date}}</label><p>{{category}}</p><p>{{content}}</p></div>',
scope: {
date:'#',
category:'#',
content:'#'
},
link: function (scope, elem, attrs) {
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="anApp" ng-controller="aCtrl">
<div ng-repeat="d in data">
<news-listing date="{{d.date}}" category="{{d.category}}" content="{{d.content}}" ></news-listing>
</div>
</div>
Here is a working example of what you want: https://jsfiddle.net/jonva/kuk3pbbz/
.directive('newsListing', function() {
return {
restrict: 'AE',
replace: 'true',
template: '<div> < span class = "glyphicon glyphicon-list-alt logo-green" > < /span> < label > {{dateValue}} < /label> < label > {{category}} < /label> < label class = "noBorder" > {{content}} < /label>',
scope: {
dateValue: '#',
content: '#',
category: '#',
},
link: function(scope, elem, attrs) {
//Fairly sure this is where the binding needs to happen?
}
};
});
create the custom directive for radio buttons in angular js
i tried so far
HTML:
<my-raido></my-raido>
<my-raido></my-raido>
<my-raido></my-raido>
Angular js:
var App = angular.module('myRaido',[]);
App.directive('myRaido',function() {
return {
restrict : 'E',
template: '<div class="myClass"><input type="radio"></div>',
replace:true,
link:function (scope, element, attrs) {
element.click(function () {
console.log("clicked....");
// body...
});
console.log("link should be work as per our expections...", + attrs.valve);
}
}
});
Advance Thanks
You should set a name attribute on your radio elements to make them a part of a group.
angular.module('app', [])
.directive('myRadio', function() {
return {
restrict : 'E',
template: '<div class="myClass">\
<label>\
<input type="radio">\
<span></span>\
</label>\
</div>',
replace: true,
link: function (scope, element, attrs) {
var $radio = element.find('input');
var $span = element.find('span');
$radio.attr('name', attrs.group);
$span.html(attrs.label);
}
}
});
If more than one input[radio] controls have a same name, they will behave as a group.
You would use this directive like this:
<my-radio group="group1" label="Option1"></my-radio>
<my-radio group="group1" label="Option2"></my-radio>
<my-radio group="group1" label="Option2"></my-radio>
var App = angular.module('myRaido',[]);
App.directive('myRaido',function() {
return {
restrict : 'E',
template: '<div class="myClass"><input type="radio" name='fooRadios'></div>',
replace:true,
link:function (scope, element, attrs) {
element.click(function () {
console.log("clicked....");
// body...
});
console.log("link should be work as per our expections...", + attrs.valve);
}
}
});
I have just started using AngularJS. Is there a way to use a directive from an another directive ?
I would like to add new <div time></div> on click on the parent.
EDIT : index.html
<div class="time" addtime ng-click="addTime()">
<!-- ADD NEW <div resizable draggable ...></div> from directive 'time' HERE -->
</div>
EDIT : directive.js
dragDirectives.directive('addtime', function() {
return {
restrict: 'A',
link: function(scope, element, attr, ctrl) {
},
controller: function addtimeCtrl($scope, $element){
$scope.addTime = function() {
// ADD NEW <div resizable draggable ...></div> from directive 'time'
};
}
}
});
dragDirectives.directive('time', function() {
return {
restrict: 'A',
template: '<div resizable draggable class="duree" ng-class="{\'resize-active\': isResizeActive, \'drag-active\': isDragActive }" ng-style="{ width: myWidth, left: myLeft }">',
link: function(scope, element, attr) {
}
}
});
With Angular you do not do DOM-related or jQuery-ish stuff (i.e. addEventListener). The approach would be:
Have a model describe the <div time> elements you have, e.g.:
scope.timeElements = [];
Itarate over it in the template:
<div time ng-repeat="t in timeElements"></div>
Handle the event by manipulating the model, e.g.:
(HTML)
<div class="time" addtime ng-click="addTime()">
(JS)
scope.addTime = function() {
scope.timeElements.push(something);
};
This is only an outline for a real solution, as many details are still missing, but you should get the idea. A fiddle would help getting more specific.
Also check out this.
require: '^parent' // a better way to go
dragDirectives.directive('addtime', function() {
return {
restrict: 'A',
template: '<div time ng-repeat="t in timeElements"></div>',
link: function(scope, element, attr, ctrl) {
scope.timeElements = [1, 2, 3]
},
controller: function addtimeCtrl($scope) {
this.addTime = function() {
$scope.timeElements.push($scope.timeElements.length + 1);
};
}
}
});
dragDirectives.directive('time', function() {
return {
restrict: 'A',
require: '^addtime',
template: '<div ng-click="addTime()">time</div>',
link: function(scope, element, attr, ctrl) {
scope.addTime = ctrl.addTime;
}
}
});
iI have this directive :
amDirective.directive('directiveList', function() {
return {
restrict: 'A',
scope: {
'event': '&onEvent'
},
transclude: true,
templateUrl: ''
};
});
and in my page html
<div data-dy-directive-list data-elements="elements" on-event="listItemClicked(item)"></div>
and in my directive- template html
<table class="table" data-ng-show="elements!=null && elements.length>0">
<tr data-ng-repeat="element in elements">
<td><span data-ng-click="event(element)">{{element.title}}</span></td>
</tr>
<tr></tr>
</table>
How can I pass in my directive the complex object "item"?
angular directives use '&' to bind to parent scope expressions.
It means that your directive would evaluate it when an event occurs inside the directive.
Example
app.directive('directiveList', function() {
return {
restrict: 'A',
scope: {
'event': '&onEvent'
},
link: function(scope){
var myItem = {}
scope.event = function(item) {
element.bind('click', function(){
scope.event({item: myItem})
})
}
};
});
If you want to raise an event from the parent scope and let your directive know you should use "="
Example
app.directive('directiveList', function() {
return {
restrict: 'A',
scope: {
'event': '=onEvent'
},
link: function(scope){
scope.event = function(item) {
// manipulate item
return "something";
}
}
};
});
From your directive (either controller or link function) you would call: scope.event({item: item}), passing a named map from argument names to values to provide to the callback.
Example:
amDirective.directive('directiveList', function() {
return {
restrict: 'A',
scope: {
'event': '&onEvent'
},
transclude: true,
templateUrl: '',
link: function(scope, element, attrs) {
element.bind('click', function() {
scope.event({ item: { hello: 'world', x: 3 } });
});
}
};
});
Usage:
<a directive-list on-event="myHandler(item)">Click Me<a>
Here's an example plnkr.
See: Can an angular directive pass arguments to functions in expressions specified in the directive's attributes?
This should not be too hard a thing to do but I cannot figure out how best to do it.
I have a parent directive, like so:
directive('editableFieldset', function () {
return {
restrict: 'E',
scope: {
model: '='
},
replace: true,
transclude: true,
template: '
<div class="editable-fieldset" ng-click="edit()">
<div ng-transclude></div>
...
</div>',
controller: ['$scope', function ($scope) {
$scope.edit = ->
$scope.editing = true
// ...
]
};
});
And a child directive:
.directive('editableString', function () {
return {
restrict: 'E',
replace: true,
template: function (element, attrs) {
'<div>
<label>' + attrs.label + '</label>
<p>{{ model.' + attrs.field + ' }}</p>
...
</div>'
},
require: '^editableFieldset'
};
});
How can I easily access the model and editing properties of the parent directive from the child directive? In my link function I have access to the parent scope - should I use $watch to watch these properties?
Put together, what I'd like to have is:
<editable-fieldset model="myModel">
<editable-string label="Some Property" field="property"></editable-string>
<editable-string label="Some Property" field="property"></editable-string>
</editable-fieldset>
The idea is to have a set of fields displayed by default. If clicked on, they become inputs and can be edited.
Taking inspiration from this SO post, I've got a working solution here in this plunker.
I had to change quite a bit. I opted to have an isolated scope on the editableString as well because it was easier to bind in the correct values to the template. Otherwise, you are going to have to use compile or another method (like $transclude service).
Here is the result:
JS:
var myApp = angular.module('myApp', []);
myApp.controller('Ctrl', function($scope) {
$scope.myModel = { property1: 'hello1', property2: 'hello2' }
});
myApp.directive('editableFieldset', function () {
return {
restrict: 'E',
scope: {
model: '='
},
transclude: true,
replace: true,
template: '<div class="editable-fieldset" ng-click="edit()"><div ng-transclude></div></div>',
link: function(scope, element) {
scope.edit = function() {
scope.editing = true;
}
},
controller: ['$scope', function($scope) {
this.getModel = function() {
return $scope.model;
}
}]
};
});
myApp.directive('editableString', function () {
return {
restrict: 'E',
replace: true,
scope: {
label: '#',
field: '#'
},
template: '<div><label>{{ label }}</label><p>{{ model[field] }}</p></div>',
require: '^editableFieldset',
link: function(scope, element, attrs, ctrl) {
scope.model = ctrl.getModel();
}
};
});
HTML:
<body ng-controller="Ctrl">
<h1>Hello Plunker!</h1>
<editable-fieldset model="myModel">
<editable-string label="Some Property1:" field="property1"></editable-string>
<editable-string label="Some Property2:" field="property2"></editable-string>
</editable-fieldset>
</body>
You can get access to parent controller by passing attribute in child directive link function
link: function (scope, element, attrs, parentCtrl) {
parentCtrl.$scope.editing = true;
}