Bert Duyck Bert Duyck - 6 months ago 31
AngularJS Question

Get item from ng-repeat in nested directive based on html from content-objects

Hy,
this is not easy to ask so you could understand my problem but:

I am trying to develop an application in angular that will return a html page from objects with inners.
something like this:

{
elementType: "div",
inners: [ "H1", "row" ],
attributes : [
{ name: "ng-style", value: {background: "red }
]
}


So i have an editor to edit attributes, add attributes, put new content, ...
Its impossible to put the all my code how this works but i loop a directive diContents to create templates from the object.
Its been called this way:

<di-contents enable-editor="editorCtrl.editor" console="console" key="key" content="value" ng-repeat="(key, value) in content"></di-contents>


And in the directive recieve the html and call next content:

element
.html(elementTemplateHtml)
.contents().html('<di-contents enable-editor="enableEditor" console="console" content="content" key="key" ng-repeat="(key, content) in content.inner"></di-contents>')


This works but now i am trying to make it possible to add a collection and repeat content for items in the collection.
So i add an attribute in an object:

{name: "ng-repeat", value:"item in itemCollection"}


this also works, i get as many content objects as there are items and in this object i can call the item.
But i am trying to get access to the item in an inner object and this does not work.
It cant pass that item to the inner...
Probably it has something to do with $compiling the element before i add the inner objects.
the complete directive:

angular.module('pageEditor')
.directive('diContents', function ($compile, $timeout, ContentModel, _) {

var linker = function (scope, element, attrs) {

var elementType = scope.content.elementType;
var elementTemplate = ContentModel.getTemplate(elementType);


//Opbouwen van pagina
var draw = function (element, elementType, elementTemplate) {

var elementTemplateHtml = elementTemplate.html;

if (elementType == "text" || elementType == "testText") {
element
.html(elementTemplateHtml)
.contents().html('{{contentsCtrl.content.text}}');
} else {
element
.html(elementTemplateHtml)
.contents().html('<di-contents di-tester enable-editor="enableEditor" console="console" content="content" key="key" ng-repeat="(key, content) in content.inner"></di-contents>')
}

//Add attributes
_.each(scope.contentsCtrl.content.properties.attributes, function (attribute) {
var index = _.indexOf(scope.contentsCtrl.content.properties.attributes, attribute);
var properties = "contentsCtrl.content.properties.attributes[" + index + "].value";

if (scope.contentsCtrl.content.properties.attributes[index].scope === true) {

scope.$watchCollection(properties, function () {
properties = scope.contentsCtrl.content.properties.attributes[index].value;
element
.contents().attr(attribute.name, properties);
$timeout(function () {
scope.$apply();
$compile(element.contents())(scope);
});
})

} else {
element
.contents().attr(attribute.name, properties);
}
});

$compile(element.contents())(scope);
};

//Events voor editorMode
var editor = function (element, elementType, elementTemplate, isValid) {
if (isValid) {
element.contents()
.on('mouseover.editor', function (event) {
$(this)
.addClass('hoverView')
.parents().removeClass('hoverView');

event.stopPropagation();
})
.on('mouseleave.editor', function (event) {
$(this)
.removeClass('hoverView')
.addClass("gridView");

event.stopPropagation();
})
.on('click.editor', function (event) {

scope.console.content = scope.contentsCtrl.content;

scope.console.options = elementTemplate.options;

try {
scope.$apply();

} catch (err) {
console.log(err.message);
}

event.stopPropagation();

})
.addClass("gridView gridViewHeight");

//show tooltip
element.contents()
.attr('data-toggle', "tooltip")
.attr('data-placement', "top")
.attr('title', elementType + ': ' + scope.contentsCtrl.content.name);

scope.$watch('console.content', function (value) {
element.contents().removeClass('borderSelected');
if (angular.isDefined(value) && value) {
if (value == scope.contentsCtrl.content && value.elementType != 'page') {
try {
scope.console.parentContent = scope.$parent.contentsCtrl.content;
scope.console.options = elementTemplate.options;
scope.console.contentKey = scope.key;
element.contents().addClass('borderSelected');

} catch (err) {
console.error(err.message);
}
} else if (value == scope.contentsCtrl.content && value.elementType == 'page') {
element.contents().addClass('borderSelected');
scope.console.options = elementTemplate.options;
}
}

});

} else if (!isValid) {
element.contents()
.off('.editor')
.removeClass("gridView gridViewHeight");

//remove tooltip
element.contents()
.removeAttr('data-toggle')
.removeAttr('data-placement')
.removeAttr('title');
}

};

if (scope.content) {
if (angular.isDefined(elementTemplate)) {
draw(element, elementType, elementTemplate);

scope.$watch('enableEditor', function (value) {
editor(element, elementType, elementTemplate, value);
});
} else {
console.log("No template: " + elementType);
}


} else {
console.log('Content out of bounds');
$compile(element.contents())(scope);
}
};

return {
restrict: 'E',
link: linker,
controller: 'ContentsCtrl',
controllerAs: 'contentsCtrl',
scope: {
"console": "=",
"content": "=",
"enableEditor": "=",
"key": "="
}
};
});


and a template example:

var templates = {
"test": {
"html": '<div></div>',
"options": {
"attributes": [
{
"name": "Styles",
"options": [
colorOptions,
fontOptions,
textOptions
]
},
{
"name": "Classes",
"options": [
rowOptions
]
}
],
"inners": [
{
"name": "Insert Content",
"options": [
containerElements
]
}
]
},
"attributes": [
{
"name": "ng-class",
"value": ["row"]
},
{
"name": "ng-style",
"value": {}
},
{
"name": "ng-repeat",
"value": "collectionItem in collections[0].items",
"scope": true
}
],
"scope": "collectionItem",
"inner": [
"testText"
]
},
"testText": {
"elementType": "text",
"html": '<p></p>',
"options": {},
"attributes": [
{
"name": "ng-style",
"value": {"white-space": "pre-wrap"}
}
],
"inner": [
],
"text": "{{collectionItem.text}}"
},

Answer

I doubt all this is the best way to go but it works. In the controller:

    $scope.collectionItem = $scope.$parent.collectionItem;
Comments