ng-click 在指令中不起作用
Posted
技术标签:
【中文标题】ng-click 在指令中不起作用【英文标题】:ng-click not working in directive 【发布时间】:2017-11-14 22:56:45 【问题描述】:所以我正在开发这个 Angular 应用程序。 我有一个名为 visualization 的控制器和一个名为 force-layout 的指令。
在指令的 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>
函数在指令中定义如下:
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);
它不会触发任何错误。 它以前可以工作,但不是,我不明白是什么导致了问题,有什么帮助吗?
更新:完整的指令代码。
'use strict';
/**
* @ngdoc directive
* @name redesign2017App.directive:forceLayout
* @description
* # forceLayout
*/
angular.module('redesign2017App')
.directive('forceLayout', function()
return
template: '<svg ></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);
);
;
);
【问题讨论】:
请添加您的完整指令代码。 “以前工作,现在不行”。因此,文件与以前的版本进行比较。你使用版本控制吗? (如果没有,为什么不呢?)你做备份吗? (如果没有,为什么不呢?)您使用哪个 IDE? (如果没有,为什么不呢?)每次保存代码时,Eclipse 和 Netbeans 都会保留本地历史记录。只需右键单击并选择“与...本地历史比较”,然后将当前版本与上一个版本进行比较,然后再与之前的版本进行比较,等等,直到找到您破坏的内容 哇,你的指令更像是一个控制器而不是一个指令。您的模板显示的是svg
,而不是您告诉我们的三个按钮。
感谢您的回复!我们使用版本控制,但我们不了解导致问题的原因。我们是 Angular 的菜鸟,因此指令和控制器可能不遵循最佳实践,对此感到抱歉:) 这三个按钮在我粘贴的上层代码中,它是从控制器模板 HTML 文件中提取的。
嗯,是的。您的代码看起来像你们是大三学生。那么在这种情况下,请阅读使用指令的基础知识并重构您的代码:docs.angularjs.org/guide/directive
【参考方案1】:
所以我想我找到了问题所在。
该指令由<force-layout>
标记调用,该标记显示ng-if='some-condition'
指令。
由于某种原因,在评估控制器代码时,该条件不成立,整个指令,即其 HTML 和 JS,被简单地跳过:ng-click
显然不是能够将点击事件附加到尚不存在的函数。
将ng-if
替换为ng-show
解决了这个问题:显然在这种情况下代码会立即执行,并且指令存在隐藏状态,并具有所有声明的属性。
【讨论】:
以上是关于ng-click 在指令中不起作用的主要内容,如果未能解决你的问题,请参考以下文章