Ethan Tremblay
Ethan Tremblay

Reputation: 3

Passing data between directives and controller in Angular

I'm just working on a projet in Angular 1. The task is to do a DOM tree from json object and manipulate with it through native drag'n'drop DOM operations (with out jQuery and etc). I've been done parsing json-> dom function, loading json from server, some drag'n'drop event handlers. Now my question is how to update a json object (from this object I get a ul>li tree structure) when I done a DROP event. Now, code

View

<div ng-controller="TreeController">
        <ng-dom-tree 
            style="background-color: #000" 
            ng-model = "treeJson"
            class="tree" 
            ng-draggable 
            ng-droppable>
        </ng-dom-tree>
</div>

Controller

.controller('TreeController', TreeController);

TreeController.$inject = ['treeService', '$scope'];

function TreeController(treeService, $scope) {

    $scope.treeJson = '';
    treeService.getTree().success(function (data) {
        $scope.treeJson = data;
    });
}

Main directive

.directive('ngDomTree', ngDomTree)
ngDomTree.$inject = [];
function ngDomTree() {
    var isEmpty = function (object) {
        for (var key in object) {
            return false;
        }
        return true;
    };
    function createTree(tree, list) { /*creating tree -> json to dom*/}
    return {
        restrict: 'E',
        replace: true,
        link: function (scope, elt, attrs) {
            scope.$watch('treeJson', function (data) {
                if (isEmpty(data))
                    return;
                **CAN'T HANDLE DATA CHANGING HERE**
                elt.append(document.createElement('ul'));
                createTree(data, document.getElementsByTagName('ul')[0]);
            });

        }
    }
}

Sup directive

.directive('ngDroppable', ngDroppable)
ngDroppable.$inject = [];
function ngDroppable() {
    var parseTreeToJson = function(tree){/* dom to json */}
    return {
        restrict: 'A',
        link: function (scope, elt, attrs) {
            elt.on('mouseover', function (e) {

                var droppableElt = e.target || event.target;
                if (!droppableElt.classList.contains('tree__node') && !droppableElt.classList.contains('tree__branch'))
                    return;

                droppableElt.addEventListener(
                    'dragover',
                    function (e) {

                        this.classList.add('navigator');
                        e.dataTransfer.dropEffect = 'move';
                        if (e.preventDefault)
                            e.preventDefault();
                        this.classList.add('over');
                        return false;
                    },
                    false
                );

                droppableElt.addEventListener(
                    'dragenter',
                    function (e) {
                        this.classList.add('over');
                        return false;
                    },
                    false
                );

                droppableElt.addEventListener(
                    'dragleave',
                    function (e) {
                        this.classList.remove('over');
                        this.classList.remove('navigator');
                        return false;
                    },
                    false
                );

                droppableElt.addEventListener(
                    'drop',
                    function (e) {

                        if (e.stopPropagation) e.stopPropagation();
                        this.classList.remove('over');
                        let item = document.getElementById(e.dataTransfer.getData('Text'));

                        this.appendChild(item);
                        item.id = '';
                        //updating here
                        scope.treeJson = parseTreeToJson(elt[0].children[0]); 

                        return false;
                    },
                    false
                );
            });
        }
    }
}

So, In Sup directive when drop event created, and I'm reinit treeJson variable, after that I need in main directive reinitializing the tree and also in controller get new json structure from this variable, because $watch is used, but it isn't happened.

PLEASE HELP

THNKS FOR ATTENTION :)

P.S. Here it is in Plnkr.co

Upvotes: 0

Views: 428

Answers (1)

tcooc
tcooc

Reputation: 21209

Since you are using native DOM, it bypasses angular's processors. You need to call scope.$digest() after changing angular's state to tell it that something changed.

droppableElt.addEventListener(
    'drop',
    function (e) {

        if (e.stopPropagation) e.stopPropagation();
        this.classList.remove('over');
        let item = document.getElementById(e.dataTransfer.getData('Text'));
        this.appendChild(item);
        item.id = '';
        scope.treeJson = parseTreeToDOM(elt[0].children[0]);
        scope.$digest();
    },
    false
);

Upvotes: 1

Related Questions