I'm trying to wrap kendoAutocomplete in an Angular directive. The problem is that I get the following error message: TypeError: 'undefined' is not a function (evaluating 'e(data)')
Any ideas what could be the cause of the problem ?
<input id="selectDomain" select-kendo=""/>
-----
var kendo = angular.module('kendo',[]);
kendo.directive('selectKendo', function () {
var data = [
"Sweden",
"Switzerland",
"Turkey",
"Ukraine",
"United Kingdom",
"Vatican City"
];
return {
restrict: 'A',
scope: {
},
link: function (scope, element) {
console.log(element);
$(element).kendoAutoComplete({
dataSource: data,
filter: "startswith",
placeholder: "Domain",
separator: ", "
});
}
}
});
Related
I'm studying angular and trying to write treeview with dynamic load. It has some initial pre-loaded nodes, but many of them have to be loaded by demand.
I write initial tree view here jsfiddle but cannot understand how to implement lazy load.
when I click NodeLazy I want to update treeService.Nodes and this update have to refresh view
when I click any Node I want select this node by bold font and be able get selected from treeService
Sure, I could use one of existing angular tree, but I want to understand how to do this.
var app = angular.module('demo', []);
app.directive("treeView", function() {
return {
restrict: "E",
replace: true,
scope: {
t: "=src"
},
template: "<ul class='ul-node'><tree-branch ng-repeat='c in t.children' src='c'></tree-branch></ul>"
};
});
app.directive("treeBranch", function($compile) {
return {
restrict: "E",
replace: true,
scope: {
b: "=src"
},
template: "<li class='{{b.class_li}}'>{{b.name}}</li>",
controller: function($scope) {
var has_children = angular.isArray($scope.b.children);
$scope.b.class_li = has_children ? "li-node" : "li-leaf";
},
link: function(scope, element, attrs) {
var has_children = angular.isArray(scope.b.children);
if (has_children) {
element.append('<tree-view src="b"></tree-view>');
$compile(element.contents())(scope);
}
element.on("click", function(event) {
console.log("click|" + scope.b.name);
event.stopPropagation();
if (has_children) {
element.toggleClass("ul-collapsed");
}
});
}
};
});
app.service("treeService", function() {
var nodes = {
children: [
{ name: "Node_1",
children: [
{ name: "Node_1.1",
children: [{ name: "Leaf_1" }, { name: "Leaf_2" }] },
{ name: "NodeLazy_1.2", }] },
{ name: "NodeLazy_2", }]
};
return {
Nodes : nodes
};
});
app.controller("ctrl", function($scope, treeService) {
$scope.nodes = treeService.Nodes;
});
I am using angular JS right now, in the i am using ui-bootstrap typeahead
I am trying scroll on demand logic in typeahead
i have tried this:
HTML:
<div class='container-fluid' ng-controller="TypeaheadCtrl">
<pre>Model: {{selected| json}}</pre>
<input type="text" ng-model="selected" maxlength="5" typeahead="country.name for country in countries | filter:$viewValue | limitTo:8">
</div>
JS:
angular.module('plunker', ['ui.bootstrap'])
.controller('TypeaheadCtrl', function ($scope) {
$scope.selected = undefined;
$scope.countries = [
{ name: "Afghanistan", code: "AF" },
{ name: "Aland Islands", code: "AX" },
{ name: "Albania", code: "AL" },
{ name: "Algeria", code: "DZ" },
{ name: "American Samoa", code: "AS" },
{ name: "Andorra", code: "AD" },
{ name: "Angola", code: "AO" },
{ name: "Anguilla", code: "AI" },
{ name: "Antarctica", code: "AQ" },
{ name: "Antigua and Barbuda", code: "AG" },
{ name: "Argentina", code: "AR" },
{ name: "Armenia", code: "AM" },
{ name: "Aruba", code: "AW" },
{ name: "Ascension Island", code: "AC" },
{ name: "Australia", code: "AU" },
{ name: "Austria", code: "AT" },
{ name: "Azerbaijan", code: "AZ" },
{ name: "Bahamas", code: "BS" },
{ name: "Bahrain", code: "BH" },
{ name: "Bangladesh", code: "BD" },
{ name: "Barbados", code: "BB" },
{ name: "Belarus", code: "BY" },
{ name: "Zimbabwe", code: "ZW" }
];
$scope.call= function(){
alert('reached end');
};
})
.directive('ul', function () {
return {
restrict: 'E',
link: function ($scope, element, attrs) {
element.bind('scroll', function (e) {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
// alert('end reached');
$scope.call();
}
})
}
}
});
But in the above try $scope.call(); function is not calling. Any one pls help me
REFERENCE PLUNKER
My actual requirement is when the scroll reaches the end, remaining records has to show in the typeahead
Make these changes to your directive, add a callBack scope variable in directive and add a callBack attribute in HTML , type function
.directive('ul', function () {
return {
restrict: 'E',
scope: {
callBack:"&"
}
link: function (scope, element, attrs) {
scope.callBack();
})
}
}
<div ul callBack="functionName"></div>
I am trying to avoid writing the compile and/or link functions. I only want to use the controller function. Why am I getting "too much recursion"?
The data:
$scope.myTree = {
name: "Root",
id: 1,
items: [
{
name: "Arts",
id: 12,
items: [
{ name: "Sculpture", id: 220 },
{ name: "Painting", id: 221 },
{ name: "Music", id: 222 }
]
},
{
name: "Science",
id: 45,
items: [
{ name: "Biology", id: 345 },
{ name: "Chemistry", id: 346 },
{ name: "Physics", id: 347}
]
}
]
};
The markup:
<tree data="myTree" labelfield="name" valuefield="id" childrenfield="items">
<div>
This is the custom node content.
</div>
The directive:
angular.module("app").directive("tree", function ($compile) {
return {
restrict: "E",
replace: true,
transclude: true,
scope: {
labelfield: "#",
valuefield: "#",
childrenfield: "#",
data: "="
},
controller: function ($scope) {
$scope.children = []; // remember - these are NOT the model's children!!!
if ($scope.data[$scope.childrenfield] !== undefined) {
for (var i = 0; i < $scope.data[$scope.childrenfield].length; i++) {
$scope.children.push({
label: $scope.data[$scope.childrenfield][i][$scope.labelfield],
value: $scope.data[$scope.childrenfield][i][$scope.valuefield]
});
}
}
},
template: "<ul><li ng-transclude></li>" +
"<li ng-repeat='child in children'> {{child.label}}" +
"<tree labelfield='labelfield' valuefield='valuefield' childrenfield='childrenfield'></tree>" +
"</li>" +
"</ul>"
};
});
If I remove the tag in the template, it will show only the first level, otherwise, I'll get infinite recursion.
What is missing? What shouldn't be there?
It appears that while you can't include the same directive inside itself, you can include another directive that includes the first one.
angular ui tree appears to do this with the TreeNode and TreeNodes directives.
[This is a late answer, but I think some people will find this useful.]
Nested directives will cause that "too much recursion" error. You may use RecursionHelper from this post.
After adding RecursionHelper service to your angular module, you just need to compile your directive element using RecursionHelper.compile function.
compile: function(element) {
// Use the compile function from the RecursionHelper,
// And return the linking function(s) which it returns
return RecursionHelper.compile(element);
}
The fiddle I have created is given below..the issue is that the val in template of json object is not being updated even after $compile inside my dynamicContent directive. Can someone help?
http://jsfiddle.net/hyvz75cz
var app = angular.module('app', []);
app.controller('fieldController', function ($scope) {
$scope.columns = [
{ label: "First Name", name: "Fname", template: "<div>{{val}}</div>" },
{ label: "Last Name", name: "Lname", template: "<div>{{val}}</div>" },
{ label: "Email", name: "Email", template: "<div>{{val}}</div>" }
];
$scope.data = [
{ Fname: "Tom", Lname: "Assassin", Email: "tom#d.c" },
{ Fname: "chris", Lname: "Unkown", Email: "chris#d.c" },
{ Fname: "troy", Lname: "forever", Email: "troy#d.c" },
{ Fname: "bead", Lname: "trash", Email: "bead#d.c" },
];
});
app.directive('dynamicHeader', function ($compile) {
return {
restrict: 'E',
replace: true,
scope: { model : '='},
template: '<div>{{model.label}}</div>',
link: function (scope, element) {
$compile(element)(scope);
}
};
});
app.directive('dynamicContent', function ($compile) {
return {
restrict: 'E',
replace: true,
scope: {
model: '=',
val: '='
},
template: '<div>{{model}}</div>',
link: function (scope, element) {
$compile(element)(scope);
}
};
});
I corrected your plunker example:
http://jsfiddle.net/hyvz75cz/5/
scope: {
model: '=',
val: '='
},
template: '',
link: function (scope, element) {
element.append(scope.model);
$compile(element.contents())(scope);
}
I used Vojta's angularJS directive but sometimes ckeditor would fail to display the data from a service. This almost never happened on a refresh, but often happened when navigating back to the page. I was able to verify that the $render function was always calling ck.setData with the correct data, but sometimes it would not display.
It appears that the $render method was sometimes called before ckeditor was ready. I was able to resolve this by adding a listener to the instanceReady event to make sure that it was called at least once after ckeditor was ready.
ck.on('instanceReady', function() {
ck.setData(ngModel.$viewValue);
});
In the interest of completeness, here is the complete directive that I used.
//Directive to work with the ckeditor
//See http://stackoverflow.com/questions/11997246/bind-ckeditor-value-to-model-text-in-angularjs-and-rails
app.directive('ckEditor', function() {
return {
require: '?ngModel',
link: function(scope, elm, attr, ngModel) {
var ck = CKEDITOR.replace(elm[0],
{
toolbar_Full:
[
{ name: 'document', items : [] },
{ name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] },
{ name: 'editing', items : [ 'Find','Replace','-','SpellChecker', 'Scayt' ] },
{ name: 'forms', items : [] },
{ name: 'basicstyles', items : [ 'Bold','Italic','Underline','Strike','Subscript','Superscript' ] },
{ name: 'paragraph', items : [
'NumberedList','BulletedList','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock' ] },
{ name: 'links', items : [] },
{ name: 'insert', items : [ 'SpecialChar' ] },
'/',
{ name: 'styles', items : [ 'Styles','Format','Font','FontSize' ] },
{ name: 'colors', items : [] },
{ name: 'tools', items : [ 'Maximize' ] }
]
,
height: '290px',
width: '99%'
}
);
if (!ngModel) return;
//loaded didn't seem to work, but instanceReady did
//I added this because sometimes $render would call setData before the ckeditor was ready
ck.on('instanceReady', function() {
ck.setData(ngModel.$viewValue);
});
ck.on('pasteState', function() {
scope.$apply(function() {
ngModel.$setViewValue(ck.getData());
});
});
ngModel.$render = function(value) {
ck.setData(ngModel.$viewValue);
};
}
};
});
function updateModel() {
scope.$apply(function() {
if ( ck.getData().length ) {
ngModel.$setViewValue(ck.getData());
}
});
}
see full code:
return {
require: '?ngModel',
scope: true,
link: function (scope, element, attr, ngModel) {
if (!ngModel) return;
var ck = CKEDITOR.replace(element[0]);
ck.on('instanceReady', function() {
ck.setData(ngModel.$viewValue);
});
function updateModel() {
scope.$apply(function() {
if ( ck.getData().length ) {
ngModel.$setViewValue(ck.getData());
}
});
}
ck.on('pasteState', updateModel);
ck.on('change', updateModel);
ck.on('key', updateModel);
ck.on('dataReady', updateModel);
ngModel.$render = function() {
ck.setData(ngModel.$modelValue);
};
}
}
I also meet this issue
And when i found a new directive. It works well for me!!!
Please try this:
return {
require: '?ngModel',
scope: true,
link: function (scope, element, attr, ngModel) {
if (!ngModel) return;
var ck = CKEDITOR.replace(element[0]);
ck.on('instanceReady', function() {
ck.setData(ngModel.$viewValue);
});
function updateModel() {
scope.$apply(function() {
if ( ck.getData().length ) {
ngModel.$setViewValue(ck.getData());
}
});
}
ck.on('pasteState', updateModel);
ck.on('change', updateModel);
ck.on('key', updateModel);
ck.on('dataReady', updateModel);
ngModel.$render = function() {
ck.setData(ngModel.$modelValue);
};
}
};