I have a simple AngularJS project where I take input data from the user and produce a chart based on that data. I'm trying to figure out how to organize the code so it conforms to the MVC design pattern. In particular, I'm stuck figuring out how to propagate a form's submit event to the parent of custom directive. I'm looking for some kind of call-back mechanism.
It seems like there are several options but I haven't gotten any of them to work yet. I've considered using custom directives, ui-Router, and services (as per AngularJS: How can I pass variables between controllers?)
So far I've been trying to make the approach of custom directives work. I have a custom directive, <input-form>
that is a form which when submitted should pass its input to another custom directive, <index-chart>
. I have three controllers: one for the main app, NavigationController
, one for input InputController
that's tied to the directive <input-form>
, and one for output OutputController
that's tied to the <index-chart>
directive.
I think the NavigationController
should know how to extract the input data from the InputController
and pass it to the OutputController
. And the InputController
and OutputController
should remain agnostic so they can be reused.
I guess I've figured out everything except the flow control. The <input-form>
contains the <form ... ng-submit
, so even though I want it to remain agnostic, it is responsible for triggering the action that responds to the input being submitted by the user. Yet the code for that action should be in OutputController
which InputController
shouldn't know about.
How can I make NavigationController
respond to the submit event contained within the custom directive <input-form>
whose controller is InputController
? And how can the NavigationController
then extract data from the instance of the InputController
and invoke the code contained in OutputController
that should render the chart (i.e. renderChart()
in the code below)?
The code below is also on 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
};
}]);
})();