简体   繁体   中英

Angularjs factory data or object inaccessible directly inside the controller

I have just created an Angular JS factory (below is the code) which returns data for two datepickers (ui.bootstrap's elements) and bind to my html code, but when I am trying to modify the return $scope object by factory inside the controller its not working, I mean I cannot access the $scope.Date1 or $scope.Date2 objects which are available inside the controller (returned from factory).

var MyApp = angular.module("TestApp", ["ui.bootstrap"]);

angular.module('TestApp').factory('FirstFactory', function() {

  return {
    TwoDates: function(scope) {

      scope.clear = function() {
        scope.Date1 = null;
        scope.Date2 = null;
      };


      scope.inlineOptions1 = {
        customClass: getDayClass,
        minDate: new Date(),
        //    showWeeks: true

      };

      scope.inlineOptions2 = {
        customClass: getDayClass,
        minDate: new Date(),
        //    showWeeks: true
      };

      scope.dateOptions1 = {
        //dateDisabled: disabled,
        formatYear: 'yyyy',
        maxDate: new Date(2050, 7, 22),
        minDate: new Date(),

        startingDay: 1
      };

      scope.dateOptions2 = {
        //dateDisabled: disabled,
        formatYear: 'yyyy',
        maxDate: new Date(2050, 5, 22),
        minDate: new Date(),

        //minDate: new Date($scope.changeMin()),
        startingDay: 1
      };


      scope.toggleMin = function() {

        scope.inlineOptions1.minDate = scope.inlineOptions1.minDate ? null : new Date();
        scope.dateOptions1.minDate = scope.inlineOptions1.minDate;

        var min2 = new Date();

        scope.$watch('Date1', function() {
          min2 = scope.Date1;
          scope.dateOptions2.minDate = min2;

          if (scope.Date1 > scope.Date2) {
            //  debugger;
            scope.Date2 = scope.Date1;
            console.log("Yes It's greater");
          }
          // console.log(min2);

        });


        scope.$watch('Date2', function() {

          if (scope.Date2 < scope.Date1) {
            //debugger;
            scope.Date1 = scope.Date2;
            console.log("Yes It's lesser");
          }
          // console.log(max1);

        });
      };

      scope.toggleMin();
      scope.open1 = function() {
        scope.popup1.opened = true;
      };

      scope.open2 = function() {
        scope.popup2.opened = true;
      };

      scope.popup1 = {
        opened: false

      };

      scope.popup2 = {
        opened: false
      };

      scope.setDate = function(year, month, day) {
        scope.Date1 = new Date(year, month, day);
        scope.Date2 = new Date(year, month, day);

      };

      scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd-MM-yyyy', 'shortDate'];
      scope.format = scope.formats[2];
      scope.altInputFormats = ['M!/d!/yyyy'];

      function getDayClass(data) {
        var date = data.date,
          mode = data.mode;
        if (mode === 'day') {
          var dayToCheck = new Date(date).setHours(0, 0, 0, 0);

          for (var i = 0; i < scope.events.length; i++) {
            var currentDay = new Date(scope.events[i].date).setHours(0, 0, 0, 0);

            if (dayToCheck === currentDay) {
              return scope.events[i].status;
            }
          }
        }

        return '';
      }
    }
  };
});


angular.module('TestApp').controller('StartDate', function($scope, $log, FirstFactory) {

  //debugger;
  FirstFactory.TwoDates($scope);

  //or
  console.log($scope.Date1);
});
<fieldset>
  <form name="MeForm" novalidate>
    <div ng-controller="StartDate">
      <div class="row">
        <div class="col-md-3">
          <div>
            <p class="input-group">

              <input type="text" name="fdate" class="form-control" uib-datepicker-popup="{{format}}" ng-model="Date1" is-open="popup1.opened" datepicker-options="dateOptions1" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />

              <span class="input-group-btn">
                                <button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
                            </span>
              <p class="error validationerror" ng-show="MeForm.fdate.$invalid && MeForm.fdate.$touched">First date is required</p>

            </p>
          </div>

          <input type="text" [ng-value="Date1" ] />@*{{Date1 | date: 'dd-MM-yyyy'}}*@


          <div>

            <p class="input-group">
              <input type="text" name="ldate" class="form-control" uib-datepicker-popup="{{format}}" ng-model="Date2" is-open="popup2.opened" datepicker-options="dateOptions2" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />

              <span class="input-group-btn">
                                <button type="button" class="btn btn-default" ng-click="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
                            </span>
              <p class="error validationerror" ng-show="MeForm.ldate.$invalid && MeForm.ldate.$touched">Last date is required</p>

            </p>
          </div>
          @*{{Date2 | date: 'dd-MM-yyyy'}}*@
        </div>

      </div>

    </div>

    <div>

      <input type="text" name="firstname" ng-required="true" ng-model="user.firstname" placeholder="Enter your first name" class="form-control" />
      <p class="error validationerror" ng-show="MeForm.firstname.$invalid && MeForm.firstname.$touched">You must fill out your first name</p>


      <br />
      <input type="text" name="lastname" ng-required="true" ng-model="user.lastname" placeholder="Enter your first name" class="form-control" />
      <p class="error validationerror" ng-show="MeForm.lastname.$invalid && MeForm.lastname.$touched">You must fill out your last name</p>

      <br />

      <button type="submit" class="btn submitbtn">Submit</button>
    </div>

  </form>
</fieldset>

You constructed your factory return statement very oddly. Instead of this:

angular.module('TestApp').factory('FirstFactory', function() {
  return {
    TwoDates: function(scope) {

      scope.example = function() {
        //logic
      }

      //etc functions
    }
  }
}

Try it like this instead.

angular.module('TestApp').factory('FirstFactory', function() {

  var Date1 = 0;
  var Date2 = 0;

  TwoDates.example = function(){
    //logic on Date1 or Date2
  }

  //TwoDates.exampleFunction = function(){....

  return TwoDates; //Important!
}

Notice that the factory's purpose is to return an object that contains all of your logic and variables.

This way you'll be able to use the Date1 and Date2 variables from within the factory and in any controllers that you use the factory in using factoryInstance.getDate1 .

In the end your code (the very basics at least) will look like this

var MyApp = angular.module("TestApp", ["ui.bootstrap"]);

angular.module('TestApp').factory('FirstFactory', function() {
  var Date1 = 0;
  var Date2 = 0;

  TwoDates.incrDate1 = function(){
    Date1 += 1;
  }

  TwoDates.getDate1 = function(){
    return Date1;
  }

  return TwoDates;
}

angular.module('TestApp').controller('StartDate', function($scope, FirstFactory) {

  //get *function* that returns variables from Factory
  //notice that I don't use FF.getDate1(), but instead pass the function without invoking it
  $scope.getDate1 = FirstFactory.getDate1; //<-- no ()

  console.log($scope.getDate1); // 0

  FirstFactory.incrDate1(); // calls Factory method, uses Date1 variable

  console.log($scope.getDate1); // 1

  //you can also add other factory functions to your scope so you can use them in the html
  $scope.incrDate1 = FirstFactory.incrDate1();
});

Here's another stackoverflow question that might help you out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM