Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind array elements by id with dom class elements in directive?

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>
like image 336
luzny Avatar asked Jan 29 '15 13:01

luzny


People also ask

How do you select an element with ID element using DOM?

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.

How do you add an element to the DOM?

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.


1 Answers

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

like image 154
Griffork Avatar answered Oct 16 '22 20:10

Griffork