I'm trying to bind a page_elements
array with appropriate .grid-cell
index in string html, so that it would be displayed on the page instead within my directive. I store indexes of given cell elements and then filter them to retrieve matching page_elements objects.
However, I can't rid of the redundancy of ng-repeat
in grid where is more then one element. A removed element is replaced with an empty object {}
, but it should be spliced in order to keep grid elements in right places. Moved elements should be able to drop into other grid cells. If indexes would be properly assigned then directive should work with angular-drag-and-drop-lists, how to fix it?
How can I display ng-repeat
with matched page_elements
only once in given grid? e.g. now page_elements
where grid_id: 2
is displayed three times in ng-repeat
in third grid. How to remove permanently page element object and keep cell elements in right places? Also Drag&Drop mechanism is broken in current solution.
Current code snippet and jsfidde:
var app = angular.module('app', ['dndLists']);
app.controller('homeCtrl', function ($scope) {
$scope.html_string = "<div class='container'><div class='row'><div class='col-xs-12'><div class='row'><div class='col-xs-4 grid-cell'></div><div class='col-xs-4 grid-cell'></div><div class='col-xs-4 grid-cell'></div></div><div class='row'><div class='col-xs-4 grid-cell'></div><div class='col-xs-4 grid-cell'></div><div class='col-xs-4 grid-cell'></div></div></div></div></div>";
$scope.page_elements = [{
"grid_id": 0,
"position": 0,
"snippet": "<h4>First Grid 0</h4>",
"template": "snippet"
}, {
"grid_id": 0,
"position": 1,
"snippet": "<h2>Second Grid 0</h2>",
"template": "snippet"
}, {
"grid_id": 1,
"position": 0,
"snippet": "<h2>First Grid 1</h2>",
"template": "snippet"
}, {
"grid_id": 1,
"position": 1,
"snippet": "<h2>Second Grid 1</h2>",
"template": "snippet"
}, {
"grid_id": 2,
"position": 0,
"snippet": "<h1>First Grid 2</h1>",
"template": "snippet"
}, {
"grid_id": 2,
"position": 1,
"snippet": "<h2>Second Grid 0</h2>",
"template": "snippet"
}, {
"grid_id": 2,
"position": 2,
"snippet": "<h2>Third Grid 0</h2>",
"template": "snippet"
}, {
"grid_id": 5,
"position": 0,
"snippet": "<h2>Before Last</h2>",
"template": "snippet"
}, {
"grid_id": 5,
"position": 1,
"snippet": "<h2>Last</h2>",
"template": "snippet"
}];
$scope.page_elements_pretty = angular.toJson($scope.page_elements, true);
$scope.rmElement = function (i) {
debugger
};
})
.directive('grid', function ($compile) {
return {
restrict: 'E',
replace: true,
scope: {
html_string: '=htmlstring',
page_elements: '=pageelements'
},
link: function (scope, element, attrs) {
scope.$watch('html_string', function (html) {
element.html(html);
var grid_cell = element.find('.grid-cell');
for (var celli = 0; celli < grid_cell.length; ++celli) {
var cell_eli = '';
for (var eli = 0; eli < scope.page_elements.length; ++eli) {
if (scope.page_elements[eli].grid_id === celli) {
cell_eli += scope.page_elements.indexOf(scope.page_elements[eli]);
}
}
var cell_html = '<div class="layout-grid"><div class="drop-area"><div dnd-list="page_elements">';
cell_html += '<div ng-repeat="item in page_elements | cell_elements:\'' + cell_eli + '\'" dnd-draggable="item" dnd-moved="page_elements[page_elements.indexOf(item)].pop()" ng-click="page_elements[page_elements.indexOf(item)] = {}" ng-include="item.template + \'.html\'" dnd-effect-allowed="move"></div>';
cell_html += '</div></div></div>';
$(grid_cell[celli]).empty().append(cell_html);
}
$compile(element.contents())(scope);
});
}
};
}).filter('cell_elements', function () {
return function (page_elements, cell_eli_str) {
var cell_elms = cell_eli_str.split('').map(Number);
var matched = [];
for (var i = 0; i < page_elements.length; ++i) {
for (var j = 0; j < cell_elms.length; ++j) {
if (i === cell_elms[j]) {
matched.push(page_elements[i]);
}
}
}
return matched;
}
});
.item {
min-height: 50px;
padding-left: 0px;
}
.drop-layout .layout-grid {
margin-bottom: 15px;
}
.drop-layout .layout-grid [class^=col-] {
background-color: #eee;
background-color: rgba(86, 61, 124, .15);
border: 1px solid #ddd;
border: 1px solid rgba(86, 61, 124, .2);
}
.drop-layout div[dnd-list], .drop-layout div[dnd-list] > div {
position: relative;
}
.drop-layout .drop-area div[dnd-list] {
min-height: 50px;
padding-left: 0px;
}
.drop-layout .drop-area div {
background-color: #eee;
border: 1px solid #ddd;
display: block;
padding: 0px;
}
.drop-layout .drop-area .dndDragging {
opacity: 0.7;
}
.drop-layout .drop-area .dndDraggingSource {
display: none;
}
.drop-layout .drop-area .dndPlaceholder {
background-color: #ddd;
background-color: rgba(86, 61, 124, .2);
min-height: 48px;
display: block;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://rawgit.com/marceljuenemann/angular-drag-and-drop-lists/master/angular-drag-and-drop-lists.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<div ng-app="app">
<div ng-controller="homeCtrl" class="drop-layout">
<h1>Grid:</h1>
<grid htmlstring="html_string" pageelements="page_elements"></grid>
<script type="text/ng-template" id="snippet.html">
<div class="item">{{item.snippet}} {{item.position}}</div>
</script>
<h1>Compile dynamic HTML</h1><h5>How to live preview of filled by elements html?</h5>
<textarea ng-model="html_string" rows="5" cols="100"></textarea>
<p>Assign elements to .grid-cells: <pre>{{page_elements}}</pre></p>
</div>
</div>
In JavaScript, you can almost select any element from the DOM based on its unique ID by using the getElementById() method. It returns the first element that matches the given ID, or null if no matching element was found in the document.
To add a new element to the HTML DOM, you must create the element (element node) first, and then append it to an existing element.
Not sure if this is what you want, but after reading this post and this post I think what you actually want is ng-bind-html-unsafe
.
For ng-bind-html-unsafe, you directly reference the ng-repeat variable and the result will be used for the element's .innerHTML.
I tried editing your jsfiddle, but I'm not sure I got the desired effect: jsfiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With