JavaScript Angular $broadcast called inside ng-repeat fires multiple times angular broadcast called twice

I have nested forms in an ng-repeat with a button whose click event calls a function that does a couple of things including a $scope.$broadcast. Everything in the function triggers once except for the broadcast which triggers on per item in the ng-repeat.

I cannot move the button outside the repeat or I lose the form and data references. I have a demo plunker that shows the basic setup. If you enter values into one of the inputs and click next while monitoring the console and you should see the broadcast fire multiple times (once per ng-repeat item). What I need is a way to have the broadcast only fire once while still maintaining the reference to the form for validation checking as per the demo code.

Here is the JS and the rest is in the plunker:

(function () {
var app = angular.module('App', []),
  /** manually triggers $validate event to validate the given form */
isFormValid = function ($scope, ngForm) {
  var i = null;
  //$scope.$emit('$validate');
  $scope.$broadcast('$validate');

  if(! ngForm.$invalid) {
    return true;
  } else {
    // make the form fields '$dirty' so that the validation messages would be shown
    ngForm.$dirty = true;

    for(i in ngForm) {
      if(ngForm[i] && ngForm[i].hasOwnProperty && ngForm[i].hasOwnProperty('$dirty')) { // TODO: is 'field.$invalid' test required?
        ngForm[i].$dirty = true;
      }
    }
  }
};

app.controller('appCtrl', ['$scope', function ($scope) {


    $scope.wizardStep = 1;
    $scope.nextStep = function () {
      var ngForm = $scope['stepForm_' + $scope.wizardStep];
      if(isFormValid($scope, ngForm)) { // trigger manual validation
        $scope.wizardStep++;
      }
    };
    $scope.prevStep = function () {
      $scope.wizardStep--;
    };
    $scope.submit = function () {
      var ngForm = $scope['stepForm_' + $scope.wizardStep]; // we can make this line common
      if(isFormValid($scope, ngForm)) {
        alert('Form is valid. Submitting...');
      }
    };

  }]);
})();

Any help or ideas are greatly appreciated and I know things like styles in the html and other aspects of the demo code are no-no's. I just did those to get the plunkr up faster.

TIA

Answer:1

The event is fired only once. The problem is that the testCtrl is beeing used 3 times so it's catching the event 3 times.

You need to create separate controllers for each step. A hack could be debouncing the $on handler if you really must, but I would just create separate controllers with the logic in a common service. Or maybe a base controller and child controllers (inheritance between them)

Answer:2

Updated Plunker

You are instantiating the controller repeatedly in each template. You just need to instantiate it one time by wrapping your form with a div that has the ng-controller directive:

    <div ng-controller="testCtrl">
      <form name="wizardForm" novalidate="">
        <div ng-repeat="step in steps" ng-init="stepForm ='stepForm' + ($index + 1)">
          <ng-form name="{{stepForm}}" ng-show="currentStep == $index + 1">
            <div ng-include="step.partial"></div>
            <div class="form-group wiz-btns">
              <div class="col-md-12 text-center">
                <button ng-show="currentStep > 1" type="button" class="btn btn-green" ng-click="prevStep()">
                  <span class="glyphicon glyphicon-circle-arrow-left"></span>


                Previous
              </button>
                <button ng-show="currentStep < steps.length" type="button" class="btn btn-green" ng-click="nextStep(wizardForm[stepForm])">
                Next                                         <span class="glyphicon glyphicon-circle-arrow-right"></span>
                </button>
                <!-- TODO: final submit buton -->
                <!--<button></button>-->
              </div>
            </div>
          </ng-form>
        </div>
      </form>
    </div>

Remove the directive from the partials, so you have just this:

<label class="wiz-label" for="title">Step1 Input:</label>
<input type="text" class="form-control" name="step1" ng-model="data.step1" required/>
<span ng-show="stepForm1.$dirty && stepForm1.step1.$invalid" style="background:red;">Input required</span > 
Answer:3

I am using the following function(which i got from web) to resize the column in kendo ui. this is based on Index, i am looking out to see if there can be an option to select by column title or field/...

I am using the following function(which i got from web) to resize the column in kendo ui. this is based on Index, i am looking out to see if there can be an option to select by column title or field/...

  1. kendo resize columns
  2. kendo column resize event
  3. kendo autofit column
  4. kendo grid resize column
  5. kendo grid resize column programmatically
  6. kendo grid resize column angular
  7. kendo grid resize column width
  8. kendo grid resize column jquery
  9. kendo grid resize column event
  10. kendo grid resize column mvc
  11. kendo treelist resize column
  12. kendo ui resize columns
  13. kendo grid resize columns javascript
  14. kendo grid column resize not working
  15. kendo ui grid resize columns
  16. kendo grid column resize not working in chrome
  17. kendo grid auto resize column
  18. kendo grid column resize handle width
  19. kendo grid column resize false
  20. kendo grid cannot resize columns

I need to convert session.lastAccessedTime object from jsp into Javascript Date object. Currently, it displays as long object. How can I convert to Javascript date object? console.log('...

I need to convert session.lastAccessedTime object from jsp into Javascript Date object. Currently, it displays as long object. How can I convert to Javascript date object? console.log('...

I'm trying to dubug next JavaScript code in on my HTML page: var langs = document.getElementsByClassName('ss-code-language'); for (var i in langs) { langs[i].classList.remove('ss-highlighted'); ...

I'm trying to dubug next JavaScript code in on my HTML page: var langs = document.getElementsByClassName('ss-code-language'); for (var i in langs) { langs[i].classList.remove('ss-highlighted'); ...

  1. canvas
  2. canada
  3. cancelled
  4. canceled vs cancelled
  5. canada vaccines
  6. canada goose
  7. cane corso
  8. canes
  9. canadian prime minister
  10. cancun flights
  11. canker sore
  12. candy
  13. cancer
  14. cancun
  15. canon
  16. canvas prints
  17. cancer sign
  18. candace owens
  19. canada news
  20. candytopia

I have 4 image tags with the id's of: picture_off picture_on go_forward go_backward picture_off and picture_on when clicked work. However, go_forward is supposed to, when clicked, to make a div ...

I have 4 image tags with the id's of: picture_off picture_on go_forward go_backward picture_off and picture_on when clicked work. However, go_forward is supposed to, when clicked, to make a div ...

  1. javascript buttons not working
  2. javascript buttons not working chrome
  3. javascript buttons not working in lightning
  4. javascript buttons don't work
  5. javascript buttons not working internet explorer
  6. javascript buttons stopped working
  7. firefox javascript buttons not working