I'm using bootstrap-colorpicker in combination with an angular directive.
Inside my form is colorpicker which I want to watch for changes.
As the value of the colorpicker is updated by this colorpicker jQuery plugin this does not work. I understand I have to implement this in my directive but can't figure out how.
Inside my I have the following markup:
<div data-colorpicker class="input-group colorpicker-element">
<input id="background" type="text" class="form-control" data-ng-model="myModel.background" />
<span class="input-group-addon"><i></i></span>
</div>
This markup is needed by bootstrap-colorpicker. Note I added data-colorpicker directive which initializes the colorpicker with:
myDirectives.directive('colorpicker', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.colorpicker();
}
};
});
So far so good. Note that the colorpicker is hooked up on wrapping div, which I thin kis causing my problem.
I extended the code to something like:
myDirectives.directive('colorpicker', function() {
return {
restrict: 'A',
require : '?ngModel',
link: function(scope, element, attrs, ngModel) {
element.colorpicker().on('changeColor', function(ev) {
scope.$apply(function() {
ngModel.$setViewValue(ev.color.toHex());
});
});
}
};
});
but the problem is the ngModel is defined on the input and not on the wrapping div.
Can I access the child scope/ngModel?
The easiest way is to wrap all the html in a directive.
The template:
<div class="input-group colorpicker-element">
<input id="background" type="text" class="form-control" data-ng-model="ngModel" />
<span class="input-group-addon"><i></i></span>
</div>
Directive code:
myDirectives.directive('colorpicker', function() {
return {
restrict: 'E',
require : '?ngModel',
scope: {
'ngModel': '='
},
link: function(scope, element, attrs, ngModel) {
element.colorpicker().on('changeColor', function(ev) {
scope.$apply(function() {
ngModel.$setViewValue(ev.color.toHex());
});
});
},
templateUrl: '/partials/colorpicker.html'
};
});
Then you can use it in controller:
<colorpicker ng-model="myModel.background" />
Related
I'm using compile in my directive controller to get the first directive element and compile it and then use it for other purpose I don't want to use the linking method of my directive, is there anyway to get rid this error ?
I've reproduced the issue in this JSFIDDLE:
var app = angular.module('app', []);
app.directive('panel', function ($compile) {
return {
restrict: "E",
replace: true,
transclude: true,
template: "<div><h1>handrouss</h1><div ng-transclude ></div></div>",
controller: function($scope, $element) {
var el = $compile($element.find('div')[0])($scope); // <--- this causing the issue
$scope.handrouss = el.html();
},
link: function (scope, elem, attrs) {
}
}
});
app.directive('panel1', function ($compile) {
return {
restrict: "E",
replace:true,
transclude: true,
template:"<div ng-transclude></div>",
link: function (scope, elem, attrs) {
elem.children().wrap("<div>");
}
}
});
HTML :
<div data-ng-app="app">
<panel1>
<panel>
<input type="text" ng-model="firstName" />{{firstName}}
</panel>
<input type="text" ng-model="lastname" />
</panel
Remove the ng-transclude attribute from the element before compiling in the controller.
app.directive('panel', function ($compile) {
return {
restrict: "E",
replace: true,
transclude: true,
template: "<div><h1>handrouss</h1><div ng-transclude ></div></div>",
controller: function($scope, $element) {
var div = $element.find('div');
//REMOVE ng-transclude attribute
div.removeAttr('ng-transclude');
var el = $compile(div[0])($scope);
$scope.handrouss = el.html();
},
link: function (scope, elem, attrs) {
}
}
});
As the transclusion has already been done in the compile phase of the directive the ng-transclude directive is no longer needed when compiling in the controller.
The DEMO on JSFiddle
I'm a newbie in Angular, so my apologies in advance for any silly mistakes. I have defined a textField input through a directive in Angular:
.directive('textField', function () {
return {
restrict: 'E',
scope: true,
require: 'ngModel',
template: '{{start}}<span class="text-field-cursor">{{end}}</span>',
controller: 'TextFieldController',
link: function (scope, elem, attrs, ngModel) {
scope.keyboardOptions.limitTo = parseInt(attrs.limitTo);
scope.keyboardOptions.caps = _.has(attrs, 'caps');
scope.model = ngModel;
elem.bind('click', function () {
scope.openKeyboard();
});
elem.on('$destroy', function clickDestroyElement() {
elem.unbind();
});
}
};
})
Then, on my HTML, I wrote
<text-field class="text-field" data-t-username focusable request-focus="true" ng-class="{ 'is-focused': (focused || active), 'is-active': active }" ng-model="data.username" placeholder='Enter your username here' limit-to="32"></text-field>
However, the placeholder is not being visualized on the web page. What am I doing wrong?
In your directive, the template isn't an input. So the placeholder can't work.
You can change span to input or other directive who work with placeholder.
I'm trying to create the directive, in which I need to catch the validity input inside directive and then transfer to the parent element.
Simple directive
<my-input type="text" placeholder="Simple placeholder" name="Name of input"></my-input>
Template of simple directive
<div class="my-input-wrap" ng-class="getInputClass(inputModel)">
<input type="{{type}}" name="{{name}}" placeholder="{{placeholder}}" ng-model="inputModel" />
</div><!-- ./my-input-wrap -->
Simple directive code
angular.module('angular-bootstrap')
.directive('myInput', MyInputDirective);
function MyInputDirective() {
return {
require: 'ngModel',
restrict: 'E',
scope: {
label: '#',
name: '#',
type: '#',
placeholder: '#'
},
templateUrl: 'my-input.html',
controller: MyInputController,
controllerAs: 'myInput',
link: function(scope, element, attr, NgModelController) {
// NgModelController get validation only directive not input element inside directive
scope.getInputClass = function() {
console.log('INV' + NgModelController.$invalid);
console.log('DIRT' + NgModelController.$dirty);
return {
required: NgModelController.$invalid && NgModelController.$dirty
};
};
}
};
}
function MyInputController($scope) {
//...
}
I need in directive find input and his validation ($invalid, $dirty, ...) and set class to parent element, I do not want to use the form inside.
How can I be notified when the validity of a input changes?
There is the following custom directive code:
angular.module('app.directives', ['ng']).directive('liveSearch', [
'$compile', '$timeout', function($compile, $timeout) {
return {
restrict: 'E',
replace: true,
require: 'ngModel',
scope: {
ngModel: '=',
liveSearchCallback: '=',
liveSearchSelect: '=?',
liveSearchItemTemplate: '#',
liveSearchWaitTimeout: '=?',
liveSearchMaxResultSize: '=?',
liveSearchResultField: '=?'
},
template: "<input type='text' />",
link: function(scope, element, attrs, controller) {
scope.$watch('selectedIndex', function(newValue, oldValue) {
var item;
item = scope.results[newValue];
if (item) {
scope.ngModel = '10';
element.val(item[attrs.liveSearchResultField]
}
});
}
}}]);
It's not a complete code of my directive, but it's enough to understand the problem. Also view code:
<live-search class="form-control" id="search1" live-search-callback="mySearchCallback" live-search-result-field="title"ng-model="skill" type="text"></live-search>
Value: {{ skill }}
<button class="btn btn-success" type="submit" ng-click="createEmployee">Сохранить</button>
My controller code:
$scope.createEmployee = function() {
console.log($scope.skill);
};
As you can see my custom directive has 'ng-model' attribute with name of variable 'skill'. How can I change 'skill' value in my custom directive? My way doesn't work. Thanks in advance!
In your link: try using
link:function(scope, element, attrs, ngModel){
scope.$watch('selectedIndex', function(newValue, oldValue) {
var item;
item = scope.results[newValue];
if (item) {
ngModel.$setViewValue(10);
ngModel.$render() // will update the input value as well
element.val(item[attrs.liveSearchResultField];
}
});
}
also it seems you have missed space between to separate ng-model attribute in your HTML
<live-search class="form-control" id="search1" live-search-callback="mySearchCallback" live-search-result-field="title" ng-model="skill" type="text"></live-search>
See the documentation here
When you use require: 'ngModel', the 4th parameter passed to your link function is ngModelController. Use method $setViewValue to update the value of ngModel passed to your directive, then call $render() if your view needs to be updated as well.
link: function(scope, element, attrs, ngModelController) {
scope.$watch('selectedIndex', function(newValue, oldValue) {
var item;
item = scope.results[newValue];
if (item) {
ngModelController.$setViewValue(10);
ngModelController.$render();
element.val(item[attrs.liveSearchResultField]
}
});
}
I'm trying to access a transcluded element in an element directive from a different inner directive applied within the first directive's template.
My (trivial example) setup:
Element directive
.directive('elementDirective', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'template.html',
link: function (scope, elem, attr, ctrl, transclude) {
elem.find('transclusion').replaceWith(transclude());
}
};
})
Template
<div inner-directive>
<div id="transclusion"></div>
</div>
Inner Directive
.directive('innerDirective', function() {
return {
restrict: 'A',
link: function (scope, elem, attr, ctrl) {
//Do something here with child elements (which will be transcluded).
var some = elem[0].querySelector('[name]');
//...
}
};
})
Html
<element-directive>
<input name="input_name" />
</element-directive>
My Error:
I get an error of the kind.
element-directive element has no child input elements with a 'name' attribute
I'm assuming this means that the inner directive is compiled, linked, whatnot, before transclusion happens. So, how can I achieve what I'm trying to do?