Logic for the Next button for the questionnaire?

前端 未结 3 1400
伪装坚强ぢ
伪装坚强ぢ 2021-02-15 02:21

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

3条回答
  •  情书的邮戳
    2021-02-15 02:41

    I would create three custom directives that can be used to build a multi-part form:

    1. myMultiPartForm directive would wrap the form and keep track of which part is visible
    2. myFormPart directive would be used multiple times as a wrapper for each form section
    3. myFormPartSubmit would be used on the submit button in each form part, to advance to the next part

    Here is a working example: JSFiddle

    Example

    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});
          }
        });
      }
    }
    

    Order of Operations

    To understand how all of this works, you need to understand the order in which things happen. Here is an outline:

    1. multiPartForm controller instantiated
    2. formPart A controller instantiated
    3. formPartSubmit A DOM element linked
    4. formPart A DOM element linked
    5. formPart B controller instantiated
    6. formPartSubmit B DOM element linked
    7. formPart B DOM element linked
    8. formPart C controller instantiated
    9. formPartSubmit C DOM element linked
    10. formPart C DOM element linked
    11. multiPartForm DOM element linked

    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.

提交回复
热议问题