In a nested directive, why does my child directive get the attributes of the parent directive?

I am using AngularJS + D3 to create an interactive drawing tool. I am new to both. I have a framecontainer directive that contains frames. Each frame is an svg group containing a rectangle and a drag-handle. The framecontainer handles all interactions, including adding new frames. Each frame can contain more frames. In the link function of the Framecontainer directive, I will compile a new frame and add it to add a new frame. Now when I add the frame for the first time using $ compilation it adds the frame as expected. However, when I drag the newly added frame, it seems to get its attribute as width and height from the parent DOM element. The drag and drop function takes the values ​​of the parent DOM element. Why is this happening?

This is the drag and drop function:

var dragmove=function(d) {
                    if (scope.moveable==="true") {
                        console.log("COMES HERE TOO!");
                         d.x = Math.max(0, Math.min(w - width, d3.event.x));
                        d.y = Math.max(0, Math.min(h - height, d3.event.y));
                        d3.select(dragrect[0].parentNode).attr("transform","translate("+ d.x+","+ d.y+")");
                        translatex= d.x;
                        translatey= d.y;

                    }
                }    

      

movable is set at the beginning of the link function by reading the attribute. Outside of this dragmove function, the values ​​will be as they should be. However, inside this function, the value is similar to the parent DOM element. So scope.moveable is false even though I set it to true and outside the function to true. In addition, the frame directive requires a Framecontainer directive and uses its own controller.

Here is my frames directive:

app.directive('frames',function($compile){
return{
    restrict:'E',
    priority:20,
    scope:{

    },
    replace:true,
    require:'^^framecontainer',
    template:"<g><rect id='{{surfaceID}}' class='drawarea' ng-Dblclick='popDialog()' fill-opacity='1' ng-attr-x='{{x}}' ng-attr-y='{{y}}' ng-attr-height='{{rectheight}}' ng-attr-width='{{rectwidth}}' stroke-width='3' cursor='move' stroke='{{strokecolor}}' ng-attr-fill={{rectfill}} ></rect>"
    + "<rect ng-attr-height='{{handlerheightr}}' class='dragr' opacity='0' ng-attr-x='{{handlerxr}}' ng-attr-y='{{handleryr}}' ng-attr-width='{{handlerwidthr}}' cursor='ew-resize'  fill='#773326' ></rect>"
    + "<rect ng-attr-height='{{handlerheightl}}' class='dragl' opacity='0' ng-attr-x='{{handlerxl}}' ng-attr-y='{{handleryl}}' ng-attr-width='{{handlerwidthl}}' cursor='ew-resize'  fill='#773326'></rect>"
    + "<rect ng-attr-height='{{handlerheightt}}' class='dragt' opacity='0' ng-attr-x='{{handlerxt}}' ng-attr-y='{{handleryt}}' ng-attr-width='{{handlerwidtht}}' cursor='ns-resize'  fill='#773326'></rect>"
    + "<rect ng-attr-height='{{handlerheightb}}' class='dragb' opacity='0' ng-attr-x='{{handlerxb}}' ng-attr-y='{{handleryb}}' ng-attr-width='{{handlerwidthb}}' cursor='ns-resize'  fill='#773326'></rect>"
    +"</g>",

    compile:function(s,e) {
        return {
            post: function postLink(scope, element, attr, controller) {
                var dragbarw = 10;
                scope.surfaceID=attr.id;
                scope.rectheight = attr.height;
                scope.rectwidth = attr.width;
                scope.strokecolor = attr.stroke;
                scope.rectfill = attr.fill;
                scope.x = attr.x;
                scope.y = attr.y;
                scope.handlerheightr = attr.height;

                scope.handlerwidthr=dragbarw;
                scope.handlerheightl = scope.rectheight;

                scope.handlerwidthl=dragbarw;
                scope.handlerheightt=dragbarw;
                scope.handlerheightb=dragbarw;
                scope.handlerwidtht=scope.rectwidth;
                scope.handlerwidthb=scope.rectwidth;

                scope.moveable=attr.mv;

                var w = 800;
                var h = 500;
                var width = scope.rectwidth;
                var height=scope.rectheight;
                var translatex,translatey;


                var dragrect = d3.select(element[0]).selectAll('.drawarea').attr("width","300");
                var entireContents=d3.select(element[0]).select('*');
                d3.select(element[0]).data([{x:0, y: 0}]);
                var dragbarleft=d3.select(element[0]).select(".dragl");
                var dragbartop=d3.select(element[0]).select(".dragt");
                var dragbarright=d3.select(element[0]).select(".dragr");
                var dragbarbottom=d3.select(element[0]).select(".dragb");

                // Selector and deselector
                var select = function () {
                    controller.addToSelection('#'+d3.select(this).attr("id"));
                    //controller.addToSelection(this);
                    d3.select(this).attr('stroke-dasharray', '5 5')
                        .on('click', deselect);

                };
                var deselect = function () {
                    controller.popFromSelection('#'+d3.select(this).attr("id"));
                    d3.select(this).attr('stroke-dasharray', '')
                        .on('click', select);
                };

                d3.select(element[0]).select('.drawarea').on('click', select);
                function rdragresize(d) {

                    var dragx = Math.max(d.x + (dragbarw / 2), Math.min(w, d.x + width + d3.event.dx));
                    width = dragx - d.x;
                    dragbarright.attr("x", function (d) {
                        return dragx;
                    });
                    dragrect.attr("width", width);
                    dragbarright.attr("x", dragx);
                    dragbartop
                        .attr("width", width - dragbarw)
                    dragbarbottom
                        .attr("width", width - dragbarw)
                }
                function ldragresize(d) {
                    var oldx = d.x;
                    //Max x on the right is x + width - dragbarw
                    //Max x on the left is 0 - (dragbarw/2)
                    d.x = Math.max(0, Math.min(d.x + width - (dragbarw / 2), d3.event.x));
                    width = width + (oldx - d.x);
                    dragbarleft
                        .attr("x", function(d) { return d.x - (dragbarw / 2)-translatex; });
                    dragrect
                        .attr("x", function(d) { return d.x-translatex; })
                        .attr("width", width);
                    dragbartop
                        .attr("x", function(d) { return d.x + (dragbarw/2)-translatex; })
                        .attr("width", width - dragbarw)
                    dragbarbottom
                        .attr("x", function(d) { return d.x + (dragbarw/2)-translatex; })
                        .attr("width", width - dragbarw)

                }
                function tdragresize(d){
                    var oldy = d.y;
                    d.y = Math.max(0, Math.min(d.y + height - (dragbarw / 2), d3.event.y));
                    height = height + (oldy - d.y);
                    dragbartop
                        .attr("y", function(d) { return d.y - (dragbarw / 2)-translatey; });

                    dragrect
                        .attr("y", function(d) { return d.y-translatey; })
                        .attr("height", height);

                    dragbarleft
                        .attr("y", function(d) { return d.y + (dragbarw/2)-translatey; })
                        .attr("height", height - dragbarw);
                    dragbarright
                        .attr("y", function(d) { return d.y + (dragbarw/2)-translatey; })
                        .attr("height", height - dragbarw);
                }
                var bdragresize=function(d){

                    var dragy = Math.max(d.y + (dragbarw/2), Math.min(h, d.y + height + d3.event.dy));

                    //recalculate width
                    height = dragy - d.y;

                    //move the right drag handle
                    dragbarbottom
                        .attr("y", function(d) { return dragy - (dragbarw/2) });

                    //resize the drag rectangle
                    //as we are only resizing from the right, the x coordinate does not need to change
                    dragrect
                        .attr("height", height);
                    dragbarleft
                        .attr("height", height - dragbarw);
                    dragbarright
                        .attr("height", height - dragbarw);
                }

                var dragmove=function(d) {
                    if (scope.moveable==="true") {
                        console.log("COMES HERE TOO!");
                         d.x = Math.max(0, Math.min(w - width, d3.event.x));
                        d.y = Math.max(0, Math.min(h - height, d3.event.y));
                        d3.select(dragrect[0].parentNode).attr("transform","translate("+ d.x+","+ d.y+")");
                        translatex= d.x;
                        translatey= d.y;

                    }
                }

                scope.popDialog=function()
                {


                    var newText=angular.element('<editabletext x="'+(scope.x+scope.rectwidth/2-scope.rectwidth/10)+'" y="'+scope.y+scope.rectheight/5+'" height="'+scope.rectheight/5+'" width="'+scope.rectwidth/5+'" text="Hello!!"></editabletext>');
                    element.append(newText);
                    $compile(newText)(scope);

                }

                function stopPropagation()
                {
                    d3.event.sourceEvent.stopPropagation();

                }


                var dragr = d3.behavior.drag().origin(Object).on("drag", rdragresize).on("dragstart",stopPropagation);
                var dragl=d3.behavior.drag().origin(Object).on("drag",ldragresize).on("dragstart",stopPropagation);
                var dragt=d3.behavior.drag().origin(Object).on("drag",tdragresize).on("dragstart",stopPropagation);
                var dragb=d3.behavior.drag().origin(Object).on("drag",bdragresize).on("dragstart",stopPropagation);
                var drag=d3.behavior.drag().origin(Object).on("drag",dragmove);

                console.log("ATTR-MV outside the drag function: "+attr.mv);

                d3.select(dragrect[0].parentNode).call(drag);
                dragbarleft.call(dragl);
                dragbarright.call(dragr);
                dragbartop.call(dragt);
                dragbarbottom.call(dragb);
            }
        }
    },

    controller:function($scope,$element)
    {
        this.getHeight=function()
        {
            return $scope.height;

        }

        this.getWidth=function()
        {
            return $scope.rectwidth;

        }

        this.getPosition=function()
        {

            return {x:scope.x,y:scop.y};

        }



        //$scope.$watch('fillFromParent',function(){ if ($scope.fillFromParent)$scope.rectfill=$scope.fillFromParent;});


    }
};});    

      

Here is the frame container directive:

app.directive('framecontainer',function($compile){
return{
    restrict:'A',
    scope:{
        split:'=',
        mergeq:'=',
        fillparam:'@',
        perform:'='
    },
    priority:1,
    replace:true,
    transclude:false,
    template:'<svg><frames id ="maing" stroke="#bada55" x="0" y="0"  resize height="500" width="765" fill="#006600" mv="false"   dialog="poptextdialog()"> </frames></svg>',
    link:function(scope,element,attr)
    {
        scope.$watch('perform',function(){

            var newFrame;
            var curWidth;
            var curHeight;
            var curX,curY;
            var newFrame;
            var frameID=0;

            function getRectCor(x,y,width,height)
            {
                return {x:(parseFloat(x)-parseFloat(width)/2),y:(parseFloat(y)-parseFloat(height)/2)};
            }

            if (scope.perform) {
                switch (scope.perform.action) {
                    case 0:
                        angular.forEach(scope.selectionStack,function(value,i){

                            curWidth=100;
                            curHeight=100;

                            curX=10;
                            curY=10;


                            newFrame=angular.element('<frames data-mv="true" data-stroke="#bada55" data-x="'+curX+'" data-y="'+curY+'"   data-height="'+curHeight+'" data-width="'+curWidth+'" data-fill="#FFFFFF" id="elem'+frameID+'" ></frames>');
                            frameID=frameID+1;
                            console.log("value is "+value);

                            $(value).append(newFrame);
                            $compile(newFrame)(scope.$new(true));
                        });

                        break;

                }
            }
        });


        var firstFrame='<g frame id ="maing" stroke="#bada55" x="0" y="0"  resize height="500" width="765" fill="#006600" mv="true"   dialog="poptextdialog()"> </g>';
        element.append(firstFrame);
        $compile(firstFrame)(scope);

    },
    controller:function($scope,$element)
    {
        $scope.selectionStack=[];
        var indexSelectionStack;

        this.addToSelection=function(s){
            $scope.selectionStack.push(s);
            console.log($scope.selectionStack);
        };

        this.popFromSelection=function(s){
            var index=$scope.selectionStack.indexOf(s)
            if (index>-1){
                $scope.selectionStack.splice(index,1);
            }
        };

        $scope.$watch('fillparam',function(){
            angular.forEach($scope.selectionStack,function(value,index){
                d3.select(value).select("rect").attr("fill",$scope.fillparam);

            });

        });




    }
};});

      

Sorry for the loud recording and the super meshy code. I am new to both AngularJS and d3.

+3


source to share


1 answer


The problem has been resolved. While this may not be a common problem, I thought it would help someone in the future to post an answer. The error was pretty trivial. The drag event hoisted up to the topmost parent frame. So changing the drag and drop function to invoke the following solution to the problem:

var drag=d3.behavior.drag().origin(Object).on("drag",dragmove).on("dragstart",stopPropagation);    

      



The stopPropagation function prevents the DOM drag event from firing. Thanks to everyone for pointing me in the right direction!

+2


source







All Articles