简体   繁体   English

在嵌套指令中,为什么我的child指令获取父指令的属性?

[英]In nested directive, why is my child directive getting the attributes of the parent directive?

I am using AngularJS+D3 for creating a interactive drawing tool. 我正在使用AngularJS + D3来创建交互式绘图工具。 I am new to both. 我是两个新手。 I have a framecontainer directive which contains frames. 我有一个framecontainer指令,其中包含框架。 Each frame is a svg group containing a rectangle and drag-handles. 每个帧都是一个包含矩形和拖动句柄的svg组。 Framecontainer handles all the interaction including adding new frames. Framecontainer处理所有交互,包括添加新帧。 Each frame can contain more frame. 每个帧可以包含更多帧。 In the link function of Framecontainer directive, I compile a new frame and append it for adding new frame. 在Framecontainer指令的link函数中,我编译一个新帧并附加它以添加新帧。 Now, when I add a frame for the first time using $compile, it adds the frame as expected. 现在,当我第一次使用$ compile添加一个帧时,它会按预期添加帧。 However, when I drag the newly added frame, it seems to get its attribute like width and height from the parent DOM element. 但是,当我拖动新添加的帧时,它似乎从父DOM元素获取其宽度和高度等属性。 The drag-function is taking the values of the parent DOM element. drag-function取父DOM元素的值。 Why is this happening? 为什么会这样?

This is the drag 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;

                    }
                }    

moveable is set at the beginning of the link function by reading the attribute. 通过读取属性,可以在链接函数的开头设置moveable。 Outside this dragmove function, the values are as they should be. 在此拖动功能之外,值应该是它们应该的。 However, inside this function the value seems to be of the parent DOM element. 但是,在此函数内部,值似乎是父DOM元素。 So, scope.moveable has false even though I set it to true and outside the function the value is true. 因此,尽管我将其设置为true并且函数外部的值为true,但scope.moveable仍为false。 Also, the frame directive requires the Framecontainer directive and uses its controller. 此外,frame指令需要Framecontainer指令并使用其控制器。

Here is my frames directive: 这是我的frame指令:

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 humongous post and the super-meshy code. 抱歉,这个庞大的帖子和超网状代码。 I am new to both AngularJS and d3. 我是AngularJS和d3的新手。

The issue is solved. 问题解决了。 Though it might not be a general problem, I thought it would help someone in the future to post an answer. 虽然这可能不是一般问题,但我认为这将有助于将来发布答案。 The bug was quite trivial. 这个错误非常简单。 The drag event was bubbling up to the top-most parent frame. 拖动事件冒泡到最顶层的父框架。 So, changing the drag function to call to following solved the problem: 因此,更改拖动功能以调用以下解决了问题:

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

stopPropagation function prevents the drag event from bubbling up the DOM. stopPropagation函数可防止拖动事件冒泡DOM。 Thank you everyone for pointing me in the right direction! 谢谢大家指点我正确的方向!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM