3

I Made a factory that keeps the information in my scopes in a series of 6 pages. Now when the user completes the 6th page and pushes the object I want the factory to reset to empty arrays again.

I already tried a lot with the timeout and apply elements, also tried a lot of combinations to set the array to empty (null, "", {}). but it still loads the old information when I load the page again(page 1/6).

The submit function (That also needs to reset the scopes) is

$scope.send = function(){
    if(ArrayInfo.Checkmark == true){
        firebase.database().ref('lorem/' + ArrayInfo.Ordernumber).set({
          info: ArrayInfo,
          Dates: Dates,
          gasmeter: gasmeter,
          gasmeter1: gasmeter1  
        }).then(function(){
          firebase.database().ref('lorem2/' + ArrayInfo.currentYear).set({
            last_number: ArrayInfo.Ordervalue
          });
        }).then(function(){
          //ArrayInfo = {};
          setTimeout(function(){
            ArrayInfo = "";
            $scope.info = "";
            $scope.$apply();
            $scope.$digest();
          }, 50);

        });
      //close newrental
        setTimeout(function(){
          if (window.confirm('Information saved! You are ready to leave this screen? no changes possible after this point'))
          { 
            //disable back button in home 
            $ionicHistory.nextViewOptions({
              disableBack: true
            });
            //go home
            $state.go("app.auth");
          }
          //error close newrental
          else
          {
             alert("Take your time");
          }
        }, 50);

    }
    //error send array
    else {
      alert("Please accept the terms and conditions.");
    }
  }

My factory looks like this

mainapp.factory("infoFactory", function(){
  ArrayInfo = {};
  placeholders = {
    "licenseone" : "img/placeholder.png",
    "licensetwo" : "img/placeholder.png",
    "licensethree" : "img/placeholder.png",
    "licensefour" : "img/placeholder.png",
    "imageone" : "img/front.png",
    "imagetwo" : "img/sideleft.png",
    "imagethree" : "img/back.png",
    "imagefour" : "img/sideright.png",
    "imagefive" : "img/roof.png",
    "imagesix" : "img/placeholder.png",
    "imageseven" : "img/placeholder.png",
    "imageeight" : "img/placeholder.png"
  };
  gasmeter = {
    "url" : "img/gas/gas1.png",
    "gasvalue" : "1"
  }
  gasmeter1 = {
    "url" : "img/gas/gas1.png",
    "gasvalue" : "1"
  }
  ArrayInfo.returned = false;
  RawDate = {};
  Dates = {};

  console.log(ArrayInfo);

  return ArrayInfo;
  return gasmeter;
  return gasmeter1;
  return placeholders;
  return RawDate;
  return Dates;
})

and I load the information in my controller like this

$scope.info = infoFactory;
$scope.Dates = Dates;
$scope.RawDate = RawDate;
$scope.gasmeter = gasmeter;
$scope.gasmeter1 = gasmeter1;

The angular version I am using is "3.6.6"

Donald Duck
  • 8,409
  • 22
  • 75
  • 99

1 Answers1

1

First of all, when you put return in your code, there's no use to include additional code after that, because it will never run. You need to return an Object instead.

mainapp.factory("infoFactory", function(){
  ArrayInfo = {};
  placeholders = {
    "licenseone" : "img/placeholder.png",
     // Rest of the images
  };
  gasmeter = {
    "url" : "img/gas/gas1.png",
    "gasvalue" : "1"
  }
  gasmeter1 = {
    "url" : "img/gas/gas1.png",
    "gasvalue" : "1"
  }
  ArrayInfo.returned = false;
  RawDate = {};
  Dates = {};

  console.log(ArrayInfo);

  return { 
    ArrayInfo: ArrayInfo, 
    gasmeter: gasmeter, 
    gasmeter1: gasmeter1, 
    placeholders: placeholders, 
    RawDate: RawDate, 
    Dates: Dates 
  };
})

Now you can inject infoFactory to the controller and use it like this: infoFactory.RawDate.

Now, if you want to reset the factory, you can add a function that reset all the data:

mainapp.factory("infoFactory", function(){
  // Save a reference to the current pointer of the factory, so you won't loose it inside other scopes  
  var self = this;

  self.params = {
       ArrayInfo: {},
       placeholders: {},
       gasmeter: {},
       gasmeter1: {},
       ArrayInfo: false,
       RawDate: {},
       Dates: {}
  };

  self.reset = function() {
     self.params.ArrayInfo = {};

     self.params.placeholders.licenseone = "img/placeholder.png";

     self.params.gasmeter.url = "img/gas/gas1.png";
     self.params.gasmeter.gasvalue = "1";

     self.params.gasmeter1.url = "img/gas/gas1.png";
     self.params.gasmeter1.gasvalue = "1";

     self.params.ArrayInfo.returned = false;

     self.params.RawDate = {};

     self.params.Dates = {};
  }
  self.reset(); // Call this function by default in order to initially set the factory properties 

  return { 
    reset: self.reset, // You can export the reset function and use it outside the factory too
    ArrayInfo: self.params.ArrayInfo, 
    gasmeter: self.params.gasmeter, 
    gasmeter1: self.params.gasmeter1, 
    placeholders: self.params.placeholders, 
    RawDate: self.params.RawDate, 
    Dates: self.params.Dates 
  };
})

Now when you have a reset function, you can use it like this outside the factory: infoFactory.reset() whenever you want to reset the data to the initial state. I created inside the factory a base object (this.params = { .. }) and saved inside it all the details properties, inside the reset function I have updated those properties without breaking the original references (Working example).

The above is just an example, but you can (or perhaps should) encapsulate the params of the factory, and only allow the user to control and change the values via helper functions. Example of how to do it:

mainapp.factory("infoFactory", function(){
  var self = this;

  self.params = {
     returned: false,
  };

  return {
     setReturned: function(val) { self.params.returned = val === true; },
     returned: function() { return self.params.returned; }
  }
});

The above example will hide the actual params.returned from the user outside the factory, and only allow it to set the returned flag via helper function, i.e infoFactory.setReturned( true ); or infoFactory.setReturned( false );, and inside that setReturned function you can implement complex logic to validate the value sent to the function. Note that infoFactory.setReturned( 'invalid value!!!' ); will set the returned flag to false since i'm validating the value using the strict === operator - val === true.

Then, to get the value from the factory you call the infoFactory.returned() function - By using a function you're blocking outside access to the properties of the factory.


As a side note - Don't use setTimeout(function(){ ... }); Use $timeout and $interval and then you won't need $scope.$apply(); + $scope.$digest(); in order to manually run a digest cycle because it is being handeled nativaly by Angularjs for you

Community
  • 1
  • 1
Alon Eitan
  • 11,997
  • 8
  • 49
  • 58
  • The first version of the Factory helps me alot, im kinda confused about the second Factory tho. It looks awesome piece of code but does'nt seem to work for me. My arrayinfo doesn't get defined properly using it. I'm using the same piece of code as with the first factory '$scope.info = infoFactory.ArrayInfo;' – Jurjen Folkertsma Apr 29 '17 at 16:56
  • I literally plugged the complete Factory in place of the old one. My controllers sees self. as undefined and the self.reset() is undefined ... Probally doing something wrong :) – Jurjen Folkertsma Apr 29 '17 at 17:03
  • Okay cool, My factory is exactly the code of the second snippet right now. Nothing more nothing less. – Jurjen Folkertsma Apr 29 '17 at 17:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/142974/discussion-between-jurjen-folkertsma-and-alon-eitan). – Jurjen Folkertsma Apr 29 '17 at 17:07
  • What do you need for that? – Jurjen Folkertsma Apr 29 '17 at 17:10
  • When using the second example. What is the best way to push data to my factory from my controller? First i used this piece of code for example `ArrayInfo.Ordernumber = blabla;` Now i could use `vm.infoFactory.ArrayInfo.Ordernumber = blabla;` But that seems unnecessary long. – Jurjen Folkertsma Apr 30 '17 at 17:58
  • You should add a custom function to the factory (after `returned: function() { return self.params.returned; }` in my third snippet example, and do something like `addPlaceholder: function(name, placeholder) { self.params.placeholders[name] = placeholder; }` and then use that function **outside** the factory `infoFactory.addPlaceholder( 'licenseFive', "img/placeholder.png" );` – Alon Eitan Apr 30 '17 at 18:04
  • I build in your code and i found out the problem is exactly the same as b4, the properties that are individual reset are at their default values. But it doesn't empty the generated array (ArrayInfo as an example). – Jurjen Folkertsma May 01 '17 at 09:38
  • @JurjenFolkertsma It's unfortunately getting out of the scope, can you please open a new question with updated details? Before that, you might want to take a look at [this question](http://stackoverflow.com/questions/684672/how-do-i-loop-through-or-enumerate-a-javascript-object) - You can iterate over the object properties and remove any property that is'nt suppose to be there by default – Alon Eitan May 01 '17 at 09:43
  • 1
    for now using code like `vm.infoFactory.ArrayInfo = {};` wil do the trick in the send function. For some reason that does work now. Thank you alot for the help, really helped! – Jurjen Folkertsma May 01 '17 at 10:00
  • Now im finding out that when using my reset code it doesnt take in the presets of the array, and after the reset my arrays are completely emty. my code : – Jurjen Folkertsma Jun 14 '17 at 15:50
  • setTimeout(function(){ vm.infoFactory.ArrayInfo = {}; vm.infoFactory.Dates = {}; vm.infoFactory.RawDate = {}; vm.infoFactory.pdf = {}; vm.infoFactory.reset(); }, 5); //disable back button in home $ionicHistory.nextViewOptions({ disableBack: true }); //go home $state.go("app.home"); – Jurjen Folkertsma Jun 14 '17 at 15:50
  • when trying to log the reset function it tells me not defined console.log(vm.infoFactory.reset()); – Jurjen Folkertsma Jun 14 '17 at 16:22