【发布时间】:2015-06-14 04:01:09
【问题描述】:
我有一个简单的 AngularJS 项目,我从用户那里获取输入数据并根据该数据生成图表。我试图弄清楚如何组织代码以使其符合MVC design pattern。特别是,我一直在弄清楚如何将表单的提交事件传播到自定义指令的父级。我正在寻找某种回调机制。
似乎有几个选项,但我还没有让它们中的任何一个工作。我考虑过使用custom directives、ui-Router 和服务(根据AngularJS: How can I pass variables between controllers?)
到目前为止,我一直在尝试使自定义指令的方法起作用。我有一个自定义指令<input-form>,它是一个表单,提交时应将其输入传递给另一个自定义指令<index-chart>。我有三个控制器:一个用于主应用程序NavigationController,一个用于输入InputController,它与指令<input-form> 相关联,一个用于输出OutputController,它与<index-chart> 指令相关。
我认为NavigationController 应该知道如何从InputController 中提取输入数据并将其传递给OutputController。 InputController 和 OutputController 应该保持不可知,以便可以重复使用。
我想我已经弄清楚了除了流量控制之外的一切。 <input-form> 包含 <form ... ng-submit,因此即使我希望它保持不可知,它也负责触发响应用户提交的输入的操作。然而,该操作的代码应该在 OutputController 中,InputController 不应该知道。
如何使NavigationController 响应包含在控制器为InputController 的自定义指令<input-form> 中的提交事件?然后NavigationController 如何从InputController 的实例中提取数据并调用包含在OutputController 中应该呈现图表的代码(即下面代码中的renderChart())?
下面的代码也在 Plunker 上:http://plnkr.co/edit/wm4suXMcSUE6obYFk3hp?p=preview index.html
<html ng-app="a3d">
<div ng-controller="NavigationController as navCtrl">
<input-form ng-show="navCtrl.shouldShowInputForm()"></input-form>
<index-chart ng-show="navCtrl.shouldShowOutputChart()"></index-chart>
</div>
</html>
a3j.js
(function(){
var app = angular.module('a3d', ['input-form', 'index-chart']);
app.controller('NavigationController', function(){
this.inputMode = true;
this.shouldShowInputForm = function(){
return this.inputMode;
};
this.shouldShowOutputChart = function(){
return !this.inputMode;
};
this.flipMode = function(){
this.inputMode = !this.inputMode;
}
});
})();
input-form.html
<form name="inputForm" ng-controller="InputController as inputCtrl"
ng-submit="inputForm.$valid && ???" novalidate>
<textarea name="topic1Data" ng-model="inputCtrl.inputValues.topic1Data" rows="10" cols="30" required></textarea>
<button type="submit" class="btn btn-info btn-lg" ng-disabled="!inputForm.$valid">Compare</button>
</form>
inputForm.js
(function(){
var app = angular.module('input-form', [ ]);
app.directive('inputForm', function(){
return {
restrict: 'E',
templateUrl: 'input-form.html',
};
});
app.controller('InputController', ['$window', '$log', function($window, $log, appData){
// ...
}]);
index-chart.html
<!-- I haven't really gotten to this part yet -->
<div id="indexchart" style="min-width: 310px; max-width: 800px; height: 900px; margin: 0 auto"></div>
indexChart.js
(function(){
var app = angular.module('index-chart', [ ]);
app.directive('indexChart', function(){
return {
restrict: 'E',
templateUrl: 'index-chart.html'
};
});
app.controller('OutputController', ['$window', '$log', function($window, $log, appData){
this.renderChart = function(){
// This is where the chart should get rendered
};
}]);
})();
【问题讨论】:
-
抱歉,要处理的内容很多。 :-( Plunker 或 Fiddle 的任何机会?
-
我正在寻找解决方案,但这是一个很好的建议,谢谢@camden_kid。我不认为我写的代码那么重要,它更多的是关于 AngularJS 希望我们如何进行事件传播的问题。
-
我认为最好的方法是在指令上使用
ng-model,并在表单控制器上使用观察者$scope.$watch('inputModel',fn... -
@camden_kid 我确实将它放入 Plunker:plnkr.co/edit/wm4suXMcSUE6obYFk3hp?p=preview
-
感谢@Matho,但可以在指令上使用 ng-model 吗? stackoverflow.com/questions/14115701/…的解决方案不直接使用ng-model;它使用隔离范围并定义属性
myDirectiveVar。但是我不知道如何将这个想法应用于我的自定义输入指令(我称之为inputForm)。隔离范围方法对输出指令(我称之为indexChart)是有意义的。
标签: angularjs angularjs-directive