I am beginner in AngularJS and facing some issues. I am trying to make a questionnaire having 1 question on each page. On every Next button data is save in the database. I am tr
I would create three custom directives that can be used to build a multi-part form:
myMultiPartForm
directive would wrap the form and keep track of which part is visiblemyFormPart
directive would be used multiple times as a wrapper for each form sectionmyFormPartSubmit
would be used on the submit button in each form part, to advance to the next partHere is a working example: JSFiddle
index.html
In this file, I am using MyViewController
as the view, which will expose a part
variable for keeping track of which form part is currently being displayed, as well as a save
method that each form part can call when it is submitted.
Complete!
view.controller.js
The view controller initializes the part
variable at zero, which is the index of the first form part (form parts are stored in an array, in MultiPartFormController
).
angular.module('myApp')
.controller('MyViewController', MyViewController)
;
function MyViewController($http) {
var view = this;
view.part = 0;
view.save = function(data) {
$http({
method : 'POST',
url : 'https://example.com',
data : data
}).then(function success(res) {
/** handle success **/
view.part++;
}).catch(function error(err) {
/** handle error **/
});
};
}
multi-part-form.directive.js
Here, I define the myMultiPartForm
directive and observe the part
attribute, which is the interpolated value of view.part
. Whenever that value changes (i.e. on success after view.save
is called), it will hide all form parts except the one that view.part
now references.
angular.module('myApp')
.directive('myMultiPartForm', myMultiPartFormDirective)
.controller('MultiPartFormController', MultiPartFormController)
;
function myMultiPartFormDirective() {
return {
controller : 'MultiPartFormController',
controllerAs: 'multiPartForm',
link : postLink
};
function postLink(scope, iElement, iAttrs, multiPartForm) {
iAttrs.$observe('part', function (newValue) {
angular.forEach(multiPartForm.parts, function (part, index) {
if (index == newValue) part.show();
else part.hide();
});
});
}
}
function MultiPartFormController() {
var multiPartForm = this;
multiPartForm.parts = [];
}
form-part.directive.js
Here's where it gets cool. Each myFormPart
directive adds show
and hide
methods to its controller during the post-link phase, then adds a reference to its controller to the parts
array of the myMultiPartForm
controller. This enables myMultiPartForm
to manipulate the DOM element of each myFormPart
without needing to traverse the DOM tree using jQuery or jqLite.
angular.module('myApp')
.directive('myFormPart', myFormPartDirective)
.controller('FormPartController', FormPartController)
;
function myFormPartDirective() {
return {
bindToController: {
onSubmit: '&'
},
controller : 'FormPartController',
controllerAs : 'formPart',
link : postLink,
require : ['myFormPart', '^myMultiPartForm'],
scope : true,
template : ' ',
transclude : true
};
function postLink(scope, iElement, iAttrs, controllers) {
var formPart = controllers[0];
var multiPartForm = controllers[1];
formPart.hide = function () {
iElement.css({display: 'none'});
};
formPart.show = function () {
iElement.css({display: 'block'});
};
multiPartForm.parts.push(formPart);
}
}
function FormPartController() {
var formPart = this;
formPart.data = {};
}
form-part-submit.directive.js
Finally, this directive adds a click handler to whatever element it is applied to that will call myFormPart.onSubmit
, which in this example is always the view.save
method (but could be a different function for each form part).
angular.module('myApp')
.directive('myFormPartSubmit', myFormPartSubmitDirective)
;
function myFormPartSubmitDirective() {
return {
link: postLink,
require: '^myFormPart'
};
function postLink(scope, iElement, iAttrs, formPart) {
iElement.on('click', function() {
if (typeof formPart.onSubmit === 'function') {
formPart.onSubmit({data: formPart.data});
}
});
}
}
To understand how all of this works, you need to understand the order in which things happen. Here is an outline:
The multiPartForm
controller is instantiated first, but linked last. That means by the time its postLink function is called, its controller has all of the information it needs about each formPart. Then, the part
value gets interpolated and the first $observe callback is fired.