I have this directive:
/*html, enclosed in a ng-repeat directive*/
<textarea name="alternativaHtml" id="questao_alternativa_{{$index}}" data-ng-model="alternativa.TextoHtml" data-ck-editor></textarea>
/*javascript*/
angular
.module("fluxo_itens.directives")
.directive('ckEditor', [function () {
return {
require: '?ngModel',
link: {
"post": PostLink
}
};
}]);
function PostLink($scope, elm, attr, ngModel) {
var ck = CKEDITOR.replace(attr.id);
ck.on('pasteState', function () {
$scope.$apply(function () {
ngModel.$setViewValue(ck.getData());
});
});
ngModel.$render = function (value) {
ck.setData(ngModel.$modelValue);
};
}
the problem is that when CKEDITOR tries to create the editor instance, it can't find the element, which has its id property dinamycally generated.
Just guessing , but you can try this :
<textarea name="alternativaHtml" id="questao_alternativa_{{$index}}" data-ng-model="alternativa.TextoHtml" data-ck-editor editor-id="questao_alternativa_{{$index}}"></textarea>
Directive
angular
.module("fluxo_itens.directives")
.directive('ckEditor', [function () {
return {
scope : {
'editorId' : '='
}
require: '?ngModel',
link: {
"post": PostLink
}
};
}]);
PostLink
function PostLink($scope, elm, attr, ngModel) {
var ck = CKEDITOR.replace($scope.editorId);
ck.on('pasteState', function () {
$scope.$apply(function () {
ngModel.$setViewValue(ck.getData());
});
});
ngModel.$render = function (value) {
ck.setData(ngModel.$modelValue);
};
}
The problem was that CkEditor wasn't able to find the element because the id of the element was not set in the DOM. So I've relied on jQuery to set de element DOM property so the CkEditor can find the textarea.
I've changed this in the PostLink function
var ck = CKEDITOR.replace(attr.id);
to this:
$(elm).attr("id", attr.id).prop("id", attr.id);
var ck = CKEDITOR.replace(elm[0].id);
Now everything works fine
Related
environment
AnuglarJS 1.6x
ui-bootstrap2.5
I want to display error messages with tool tip on validation with AngularJS.
I am referring to the directive created by the following jQuery and bootstrap.js with reference to it,
How can I implement it with ui - bootstrap?
Reference sample
http://jsfiddle.net/y9ujn/5/
How to show form input errors using AngularJS UI Bootstrap tooltip?
I tried trying to add attributes of ui-tooltip at the place where tooltip was set in Query, but it does not work.
<script>
var app = angular.module("app", ['ui.bootstrap']);
app.controller('Ctrl', function ($scope) {});
app.directive('validationMessage', function () {
return {
restrict: 'A',
priority: 1000,
require: '^validationTooltip',
link: function (scope, element, attr, ctrl) {
ctrl.$addExpression(attr.ngIf || true);
}
}
});
app.directive('validationTooltip', function ($timeout) {
return {
restrict: 'E',
transclude: true,
require: '^form',
scope: {},
template: '<span class="label label-danger span1" ng-show="errorCount > 0">hover to show err</span>',
controller: function ($scope) {
var expressions = [];
$scope.errorCount = 0;
this.$addExpression = function (expr) {
expressions.push(expr);
}
$scope.$watch(function () {
var count = 0;
angular.forEach(expressions, function (expr) {
if ($scope.$eval(expr)) {
++count;
}
});
return count;
}, function (newVal) {
$scope.errorCount = newVal;
});
},
link: function (scope, element, attr, formController, transcludeFn) {
scope.$form = formController;
transcludeFn(scope, function (clone) {
/
var badge = element[0].firstChild;
var tooltip = angular.element('<div class="validationMessageTemplate tooltip-danger" />');
tooltip.append(clone);
element.append(tooltip);
$timeout(function () {
scope.$field = formController[attr.target];
badge.attr( 'uib-tooltip', "test")
});
});
}
}
});
I am trying to get parameter on click using directive.I want to get child data in the click event for checking has child or not.
.....
html
div ng-app="treeApp">
<ul>
<treeparent></treeparent>
</ul>
js
(function () {
var treeApp = angular.module('treeApp', []);
treeApp.directive('treeparent', function () {
return {
restrict: 'E',
template: "<button addchild child='m'>ajith</button><div id='new'></div>"
}
});
treeApp.directive('addchild', function ($compile) {
return {
scope: {
'child':'='
},
link: function (scope, element, attrs) {
debugger;
element.bind("click", function (scope,attrs) {
debugger;
//here i want to get hild ie 'm'
angular.element(document.getElementById('new')).append("<div><button button class='btn btn-default'>new one</button></div>");
});
}
}
});
})();
plz help me
So, i think scope.child is undefined becouse it is overlaps in declaring event.
You can define variable before event binding
link: function (scope, element, attrs) {
var child = scope.child;
element.bind("click", function (scope,attrs) {
// here you can use child
console.log('child', child);
});
}
or declare different argument names
link: function ($scope, $element, attrs) {
element.bind("click", function (scope,attrs) {
// here you can use $scope.child
console.log('$scope.child', $scope.child);
});
}
Is a callback has scope and attrs argument? May be it has only one $event argument?
link: function (scope, element, attrs) {
element.bind("click", function ($event) {
// here you can use child
console.log('child', scope.child);
});
}
Example for call method from directive in parent scope
parent template
<test-dir data-method="myFunc"></test-dir>
<button ng-click="myFunc('world')">click me</button>
or
<button test-dir data-method="myFunc" ng-click="myFunc('world')">click me</button>
directive
.directive('testDir', function() {
return {
scope: {
method: '=',
},
controller : function($scope) {
$scope.method = function(text) {
alert('hello '+text);
};
},
};
})
//My controller code
//I am getting values from database into angular js ckeditor but html tags are not applying in editor instead of it is showing html element tag code in ediator
myApp.directive('ckEditor', [function () {
return {
require: '?ngModel',
link: function ($scope, elm, attr, ngModel) {
var ck = CKEDITOR.replace(elm[0]);
ck.on('pasteState', function () {
$scope.$apply(function () {
ngModel.$setViewValue(ck.getData());
});
});
ngModel.$render = function () {
ck.setData(ngModel.$modelValue);
};
}
};
}])
myApp.controller('editcontentcontroller', function ($scope, $http)
{
$scope.ckEditors;
$http({ method: 'POST', url: 'pageedit.php' }).success(function (data)
{
// response data
$scope.id = data[0]['id'];
$scope.page = data[0]['page'];
$scope.ckEditors = data[0]['pagecontent'];
}).
error(function (data) {
console.log(data);
});
});
add following into your directive and check the CKEDITOR docs
ck.on('instanceReady', function () {
ck.setData(ngModel.$viewValue);
});
CKEDITOR.instanceReady Fired when a CKEDITOR instance is created, fully initialized and ready for interaction.
myApp.directive('ckEditor', function () {
return {
require: 'ngModel',
priority: 10,
link: function (scope, elm, attr, ngModel) {
var ck = CKEDITOR.replace(elm[0]);
if (!ngModel) return;
ck.on('instanceReady', function () {
ck.setData(ngModel.$viewValue);
});
function updateModel() {
scope.$apply(function () {
if (ck.getData().length) {
ngModel.$setViewValue(ck.getData());
}
});
}
ck.on('change', updateModel);
ck.on('key', updateModel);
ck.on('dataReady', updateModel);
ck.on('pasteState', updateModel);
ngModel.$render = function (value) {
ck.setData(ngModel.$viewValue || '');
};
}
};
})
I have the following code:
<div id='parent'>
<div id='child1'>
<my-select></my-select>
</div>
<div id='child2'>
<my-input></my-input>
</div>
</div>
I also have two directives which get some data from the data factory. I need the two directives to talk to each other such that when a value in select box is changed the input in changes accordingly.
Here's my two directives:
.directive("mySelect", function ($compile) {
return {
restrict: 'E',
scope:'=',
template: " <select id='mapselectdropdown'>\
<option value=map1>map1</option> \
<option value=map2>map2</option> \
</select>'",
link: function (scope, element, attrs) {
scope.selectValue = //dont konw how to get the value of the select
}
};
})
.directive("myInput", function($compile) {
return {
restrict: 'E',
controller: ['$scope', 'dataService', function ($scope, dataService) {
dataService.getLocalData().then(function (data) {
$scope.masterData = data.input;
});
}],
template: "<input id='someInput'></input>",
link: function (scope, element, attrs) {
//here I need to get the select value and assign it to the input
}
};
})
This would essentially do the onchange() function that you can add on selects. any ideas?
You could use $rootScope to broadcast a message that the other controller listens for:
// Broadcast with
$rootScope.$broadcast('inputChange', 'new value');
// Subscribe with
$rootScope.$on('inputChange', function(newValue) { /* do something */ });
Read Angular docs here
Maybe transclude the directives to get access to properties of outer scope where you define the shared variable ?
What does this transclude option do, exactly? transclude makes the contents of a directive with this option have access to the scope outside of the directive rather than inside.
-> https://docs.angularjs.org/guide/directive
After much research this is what worked...
I added the following:
.directive('onChange', function() {
return {
restrict: 'A',
scope:{'onChange':'=' },
link: function(scope, elm, attrs) {
scope.$watch('onChange', function(nVal) { elm.val(nVal); });
elm.bind('blur', function() {
var currentValue = elm.val();
if( scope.onChange !== currentValue ) {
scope.$apply(function() {
scope.onChange = currentValue;
});
}
});
}
};
})
Then on the element's link function I added:
link: function (scope, elm, attrs) {
scope.$watch('onChange', function (nVal) {
elm.val(nVal);
});
}
Last added the attribute that the values would get set to in the scope:
<select name="map-select2" on-change="mapId" >
I have the following code snippets:
HTML:
<div data-filedrop data-ng-model="file"></div>
Controller:
$scope.$watch('file', function(newVal) {
if (newVal) {
alert("File",newVal);
}, false);
}
Directive:
angular.module('app').directive('filedrop', function () {
return {
restrict: 'A',
templateUrl: './directives/filedrop.html',
replace: true,
scope: {
ngModel: '=ngModel'
},
link: function (scope, element) {
var dropzone = element[0];
dropzone.ondragover = function () {
this.className = 'hover';
return false;
};
dropzone.ondragend = function () {
this.className = '';
return false;
};
dropzone.ondrop = function (event) {
event.preventDefault();
this.className = '';
scope.$apply(function () {
scope.ngModel = event.dataTransfer.files[0];
});
return false;
};
}
};
});
The $watch function is never triggered when I update the $scope.
Any Ideas?? Might be an isolated scope issue? It used to work until yesterday... when I had to redo
bower install && npm install
I can confirm:
dropzone.ondrop is fired
event.dataTransfer.files[0] does contain the file being dropped
because of the bower install I also tried angular 2.1.14, 2.1.15 and 2.1.16 (current) but none are working
Thanks!
Sander
ngModel is a controller/provider, it's not a scope. It's not identical to using a scope like in a controller in any way whatsoever. You have to use ngModel.$setViewValue('some value') to manipulate the value. You also have to add the ngModel like this:
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
// do some stuff
ngModel.$setViewValue(element.html()); // example
}
I found a good tutorial which describes this perfectly: http://suhairhassan.com/2013/05/01/getting-started-with-angularjs-directive.html#.U1jme-aSzQ4
Another option would of course be to just pass a scope variable like this:
Directive:
scope: {
'someAttribute': '='
},
link: function(scope, element) {
dropzone.ondrop = function(event) {
scope.$apply(function() {
scope.someAttribute = event.dataTransfer.files[0];
});
}
}
Controller View:
<div filedrop some-attribute="mymodel"></div>
Controller:
$scope.$watch('mymodel', function(newVal) {
// yeah
});
It seems that you are not modifying the value of scope.ngModel. Instead you are overwriting variable scope.ngModel so that it points to the different object, namely: event.dataTransfer.files[0]