[英]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.