简体   繁体   English

ng-click在指令中不起作用

[英]ng-click not working in directive

so I have this Angular application I'm working on. 所以我有这个正在使用的Angular应用程序。 I have a controller called visualization and a directive called force-layout . 我有一个称为可视化的控制器和一个名为force-layout的指令。

In the HTML template of the directive I'm creating three buttons and I attach to them three corresponding functions that I define in the directive code: 在指令的HTML模板中,我创建了三个按钮,并在指令代码中定义了三个对应的函数:

    <div class="panel smallest controls">
        <span ng-click="centerNetwork()"><i class="fa fa-arrows-alt" aria-hidden="true"></i></span>
        <span ng-click="zoomIn()"><i class="fa fa-search-plus" aria-hidden="true"></i></span>
        <span ng-click="zoomOut()"><i class="fa fa-search-minus" aria-hidden="true"></i></span>
    </div>

    <force-layout ng-if=" config.viewMode == 'individual-force' || config.viewMode == 'individual-concentric' "></force-layout>

The function are defined in the directive like this: 该函数在指令中定义如下:

    scope.centerNetwork = function() {
      console.log("Recenter");
      var sourceNode = nodes.filter(function(d) { return (d.id == sourceId)})[0];
      svg.transition().duration(750).call(zoom.transform, d3.zoomIdentity.translate(width/2-sourceNode.x, height/2-sourceNode.y));
    }
    var zoomfactor = 1;
    scope.zoomIn = function() {
      console.log("Zoom In")
      svg.transition().duration(500).call(zoom.scaleBy, zoomfactor + .5);
    }
    scope.zoomOut = function() {
      console.log("Zoom Out")
      svg.transition().duration(500).call(zoom.scaleBy, zoomfactor - .25);
    }

It does not trigger any error. 它不会触发任何错误。 It was working before, not it is not and I cannot understand what is causing the problem, any help? 它曾经在工作,不是,不是,我不明白是什么导致了问题,有什么帮助吗?


UPDATE: full directive code. 更新:完整的指令代码。

'use strict';

/**
 * @ngdoc directive
 * @name redesign2017App.directive:forceLayout
 * @description
 * # forceLayout
 */
angular.module('redesign2017App')
  .directive('forceLayout', function() {
    return {
      template: '<svg width="100%" height="100%"></svg>',
      restrict: 'E',
      link: function postLink(scope, element, attrs) {
        console.log('drawing network the first time');
        // console.log(scope.data);
        var svg = d3.select(element[0]).select('svg'),
          width = +svg.node().getBoundingClientRect().width,
          height = +svg.node().getBoundingClientRect().height,
          nodes,
          links,
          degreeSize,
          sourceId,
          confidenceMin = scope.config.confidenceMin,
          confidenceMax = scope.config.confidenceMax,
          dateMin = scope.config.dateMin,
          dateMax = scope.config.dateMax,
          complexity = scope.config.networkComplexity;

        var durationTransition = 500;


        // A function to handle click toggling based on neighboring nodes.
        function toggleClick(d, newLinks, selectedElement) {

          // Some code for handling selections cutted out from here

        }

        svg.append('rect')
          .attr('width', '100%')
          .attr('height', '100%')
          .attr('fill', 'transparent')
          .on('click', function() {
            // Clear selections on nodes and labels
            d3.selectAll('.node, g.label').classed('selected', false);

            // Restore nodes and links to normal opacity. (see toggleClick() below)
            d3.selectAll('.link')
              .classed('faded', false)

            d3.selectAll('.node')
              .classed('faded', false)

            // Must select g.labels since it selects elements in other part of the interface
            d3.selectAll('g.label')
              .classed('hidden', function(d) {
                return (d.distance < 2) ? false : true;
              });

            // reset group bar
            d3.selectAll('.group').classed('active', false);
            d3.selectAll('.group').classed('unactive', false);

            // update selction and trigger event for other directives
            scope.currentSelection = {};
            scope.$apply(); // no need to trigger events, just apply
          });


        // HERE ARE THE FUNCTIONS I ASKED ABOUT

        // Zooming function translates the size of the svg container.
        function zoomed() {
          container.attr("transform", "translate(" + d3.event.transform.x + ", " + d3.event.transform.y + ") scale(" + d3.event.transform.k + ")");
        }
        var zoom = d3.zoom();
        // Call zoom for svg container.
        svg.call(zoom.on('zoom', zoomed)); //.on("dblclick.zoom", null);
        //Functions for zoom and recenter buttons
        scope.centerNetwork = function() {
          console.log("Recenter");
          var sourceNode = nodes.filter(function(d) {
            return (d.id == sourceId) })[0];
          svg.transition().duration(750).call(zoom.transform, d3.zoomIdentity.translate(width / 2 - sourceNode.x, height / 2 - sourceNode.y));
          // svg.transition().duration(750).call(zoom.transform, d3.zoomIdentity);
        }
        var zoomfactor = 1;
        scope.zoomIn = function() {
          console.log("Zoom In")
          svg.transition().duration(500).call(zoom.scaleBy, zoomfactor + .5);
        }
        scope.zoomOut = function() {
          console.log("Zoom Out")
          svg.transition().duration(500).call(zoom.scaleBy, zoomfactor - .25);
        }

        // TILL HERE

        var container = svg.append('g');

        // Toggle for ego networks on click (below).
        var toggle = 0;

        var link = container.append("g")
          .attr("class", "links")
          .selectAll(".link");

        var node = container.append("g")
          .attr("class", "nodes")
          .selectAll(".node");

        var label = container.append("g")
          .attr("class", "labels")
          .selectAll(".label");


        var loading = svg.append("text")
          .attr("dy", "0.35em")
          .attr("text-anchor", "middle")
          .attr('x', width / 2)
          .attr('y', height / 2)
          .attr("font-family", "sans-serif")
          .attr("font-size", 10)
          .text("Simulating. One moment please…");

        var t0 = performance.now();

        var json = scope.data;

        // graph = json.data.attributes;
        nodes = json.included;
        links = [];
        json.data.attributes.connections.forEach(function(c) { links.push(c.attributes) });
        sourceId = json.data.attributes.primary_people;

        // d3.select('.legend .size.min').text('j')

        var simulation = d3.forceSimulation(nodes)
          // .velocityDecay(.5)
          .force("link", d3.forceLink(links).id(function(d) {
            return d.id;
          }))
          .force("charge", d3.forceManyBody().strength(-75)) //.distanceMax([500]))
          .force("center", d3.forceCenter(width / 2, height / 2))
          .force("collide", d3.forceCollide().radius(function(d) {
            if (d.id == sourceId) {
              return 26;
            } else {
              return 13;
            }
          }))
          // .force("x", d3.forceX())
          // .force("y", d3.forceY())
          .stop();

        for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
          simulation.tick();
        }

        loading.remove();

        var t1 = performance.now();

        console.log("Graph took " + (t1 - t0) + " milliseconds to load.")

        function positionCircle(nodelist, r) {
          var angle = 360 / nodelist.length;
          nodelist.forEach(function(n, i) {
            n.fx = (Math.cos(angle * (i + 1)) * r) + (width / 2);
            n.fy = (Math.sin(angle * (i + 1)) * r) + (height / 2);
          });
        }

        function update(confidenceMin, confidenceMax, dateMin, dateMax, complexity, layout) {
          // some code for visualizing a force layout cutted out from here
        }

        // Trigger update automatically when the directive code is executed entirely (e.g. at loading)
        update(confidenceMin, confidenceMax, dateMin, dateMax, complexity, 'individual-force');

        // update triggered from the controller
        scope.$on('Update the force layout', function(event, args) {
          console.log('ON: Update the force layout')
          confidenceMin = scope.config.confidenceMin;
          confidenceMax = scope.config.confidenceMax;
          dateMin = scope.config.dateMin;
          dateMax = scope.config.dateMax;
          complexity = scope.config.networkComplexity;
          update(confidenceMin, confidenceMax, dateMin, dateMax, complexity, args.layout);
        });

      }
    };
  });

So I think I found the problem. 所以我想我找到了问题。

The directive was invoked by the <force-layout> tag, which presented the ng-if='some-condition' directive. 该指令由<force-layout>标记调用,该标记表示ng-if='some-condition'指令。

For some reason, while the controller code is evaluated, that condition doesn't prove to be true, and the directive as a whole, meaning its HTML and its JS, is simply skipped: the ng-click is then obviously not able to attach the click event to a function that does not exists yet. 由于某种原因,在评估控制器代码时,该条件并不能证明是正确的,整个指令(即其HTML和JS)被简单地跳过了:那么ng-click显然无法附加单击事件到尚不存在的函数。

Replacing ng-if with ng-show solved the issue: apparently in this case the code is executed immediately and the directive exists hidden, with all its declared properties. ng-show替换ng-if解决了这个问题:显然,在这种情况下,代码立即执行,并且该指令及其所有声明的属性都隐藏了。

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

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