0

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>
Alex M
  • 2,756
  • 7
  • 29
  • 35
Khan
  • 31
  • 8
  • As far as I know if you inject $rootScope directly to factory `app.factory("myFactory",function($rootScope){})` it will work. $scope cannot be accessed even if you pass it. Anyways, what error are you getting? – Gary Aug 18 '16 at 14:26
  • I am not getting any error with my code, but when even I am passing the $scope object to the factory and injecting the same factory to a controller(as you can see in above code), I am trying to access that in my controller which not happening. My main intention is to access the Date1 and Date2 inside the controllers so that I can assign them to any other object which I will create in the same controller. – Khan Aug 20 '16 at 11:03
  • angular.module('TestApp').controller('StartDate', function($scope, $log, FirstFactory) { //This is working and its actually returning Date1 and Date2 which I am using in my view(see above html code) FirstFactory.TwoDates($scope); //but This is what I want which is not working. console.log($scope.Date1); //so I can assign this $scope.dt1 = $scope.Date1 }); – Khan Aug 20 '16 at 11:04

1 Answers1

0

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.

Community
  • 1
  • 1
Federico Pettinella
  • 1,471
  • 1
  • 11
  • 19
  • Thanks but I did not get the above one, can you please put my factory code and access the date1 and date2 in a working controller, I am very new to Angularjs actually. – Khan Aug 20 '16 at 10:49
  • My main intention is to access the Date1 and Date2 inside the controller after injecting the factory like this: $scope.myDate1 = $scope.Date1 and $scope.myDate2 = $scope.Date2. Please help me with this, because I am stuck here. – Khan Aug 21 '16 at 09:04
  • If you use the $scope object, you can only access that object which belongs to the current controller. If you want to pull a variable from a different controller/factory, then you'll have to do that by accessing it through the responsible controller/factory. Here's a good [link about factories](http://viralpatel.net/blogs/angularjs-service-factory-tutorial/) that you could read. – Federico Pettinella Aug 22 '16 at 08:09
  • I've updated my answer to include an example controller. It's important to note that I did not pass the `$scope` object into the factory at any point. – Federico Pettinella Aug 22 '16 at 08:32