0

Here is a description of what I am trying to do:

I currently have an angular.module on my web app that I am building that is a price calculator where users will be able to put in how many days/weeks they would like to stay at a Hotel and have the module calculate their estimated price with fees/days/weeks included for the dates they would like to stay.

I currently have my select menu of seasons pulling from my angular.factory via a controller(see below). The user can select from the different options that I have stored in the factory as object literals and depending on the 'label' they have selected in the menu, it will calculate their price based on 1 weeks stay at this hotel. Great.

Now I would like to add some functionality to my steppers that I have set up through the [Revolunet/angular-stepper][1] directive that I have chosen to use as my stepper for each day and week.

The issue that I am running into is I am unsure as to where to do my logic for the calculations. I would like the user to be able to select a season in the select menu, and then use the stepper to add any additional days/weeks using the stepper and to dynamically adjust the estimated total based on how many days/weeks the user has chosen.

I know that I cannot have controllers talk to one another and I cannot have $scope look for any global variables aside from the app.factory I have set up? Could i store all of the angular-stepper stuff in the factory and have my app.controller inherit it?

So, in summary, I would like to dynamically change my dollar amount for the price estimator when the user adds days and weeks to their requests using the stepper I have provided and I am stuck as to where to put my logic for this. I hope this makes sense!

Here is my code:

HTML:

<div id= "estimator-wrapper" ng-app="priceEstimator">
    <h3> Price Estimator</h3>
    <h4> (with fees):</h4>
    <div ng-controller="weekStepper">
      <div  ng-controller="seasonSelector">
        <h2>{{ seasonsList.value }}</h2>
        <p> Select a season:</p>
        <select ng-model="seasonsList" ng-options="season as season.label for season in seasons"></select>
      </div>
      <label>Number of weeks:</label>
        <div min="minRating" max="maxRating" ng-model="rating" rn-stepper></div>
    <div ng-controller="dayStepper">
      <label>Number of days:</label>
        <div min="minRating" max="maxRating" ng-model="rating" rn-stepper></div>
      </div>
  </div>

Here is my Angular.js Module:

const app = angular.module('priceEstimator', ['revolunet.stepper']);

app.factory('seasonFactory', () => {
  let factory = {};
  let seasons = [
    { label:'-', value: '$' + 0},
    { label:'Fall/Winter', value: '$' + Math.floor((2100 + 245) * 1.115) },
    { label: 'Spring', value: '$' + Math.floor((2900 + 245) * 1.115) },
    { label: 'Summer', value: '$' + Math.floor((3995 + 245) * 1.115) }
  ];
  factory.getSeasons = () => {
    return seasons;
  };
  return factory;
});

app.controller("weekStepper",($scope) => {
  $scope.rating = 0;
  $scope.minRating = 0;
  $scope.maxRating = 8;
});

app.controller("dayStepper",($scope) => {
  $scope.rating = 0;
  $scope.minRating = 0;
  $scope.maxRating = 6;
});

app.controller("seasonSelector",($scope, seasonFactory) => {
  $scope.Math = Math;
  $scope.seasons = seasonFactory.getSeasons();
  $scope.seasonsList = $scope.seasons[0];
});
newman
  • 421
  • 2
  • 9
  • 25

1 Answers1

1

You definitely can have your controllers talk to each other and already have a parent-child relationship between the weekStepper and dayStepper because day is nested within week in your html.

You can use $parent from within day stepper to talk to the weekStepper controller or since they are nested, the child controller will automatically inherit the parent's properties.

However, since you already have the factory set up, simply inject the factory into each controller and access the properties from there. Factories are singletons, so even if you injecting it into each controller, all of those references will point to the same instance and have the same data.

Based on what I said above, because of how your controllers are nested in your html if you inject seasonFactory and into weekStepper and store it into a property (say season factory), then $scope.seasonFactory will be available in all of the controllers. You could store the data in the factory once its retrieved or move the code that stores the results of your factory methods to the outer most controller and make it available everywhere that way.

There are a lot of great questions and answers here with regard to parent & child controllers. This one is one of the more popular ones: AngularJS access parent scope from child controller

Also, if you're on angular 1.5 or later, this would be a great opportunity to start using components.

Mike Feltman
  • 5,160
  • 1
  • 17
  • 38
  • Thanks for your response. Good to know! I was not familiar with `$parent` and will look into that. Even though I have access to all of the object literals inside of the factory in every controller, I still think the issue I've been running into is that I still need access to one of the defined properties on `$scope` on the weekStepper controller inside of *another* controller. Maybe I'm thinking about this wrong, but I want to write some logic for whenever a user increases the weekStepper, it adds more to the `{{ seasonsList.value }}`, which means I need access to `$scope.minRating`, right?. – newman Jan 04 '18 at 23:34
  • I more so just don't know *where* to write the logic to make this work...I'm thinking I may need to modify the angular-stepper.js file provided by the people who made the directive... – newman Jan 04 '18 at 23:35