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>