0

I'm making a clone of ESPN's Steak for the Cash to learn AngularJS & Firebase. Reason is so the data can be real time, and just because I want to learn about it and figured it may be an easier thing to start with than using Node/Mongo for the back end.

For those of you who don't know what Steak for the Cash is, basically you answer questions one of two ways relating to sporting events being played that day, and you build up a Win/Loss record over the month based on how many you get right/wrong.

As I've been working on this, I've come up with a more specific question if this is perhaps easier to answer: So I've got "props," or, questions, and each question will have several "choices." There will need to be an answer associated with the question as well. I'd also like to add comments to the questions.

As an example: Prop - Who will score more points? Option A - Derrick Rose Option B - Lebron James Answer - Derrick Rose Comment- "ah I thought it was going to be lebron" (this user will eventually get a win/loss added to their record as well)

I have a games controller & service. In the Games service I have "var Game = {" with methods for adding/deleting games. I also have methods for "addQuestion" and it works. The code in the method is "games.$child(gameId).$child('props').$add(prop);"

Do I do the same as above for options, answers, and comments? Throw them all into the Games controller? When do they get their own controller or service? For options I was going to have something like "games.$child(gameId).$child('props').$child('options')" and so on, but that seems inefficient to me. Also I don't know how to get the propId because I'm on the gameview.html page that has the gameId in the URL.

/controllers/gameview.js

'use strict';

app.controller('GameViewCtrl', function($scope, $routeParams, Game) {
  $scope.game = Game.find($routeParams.gameId);

  $scope.addProp = function () {
    Game.addProp($routeParams.gameId, $scope.prop);
    $scope.prop = '';
  };

  $scope.deleteProp = function(prop, propId) {
    Game.deleteProp($scope.game, prop, propId);
  };

  $scope.addOption = function () {
    Game.addOption($routeParams.propId, $scope.option);
  };
});

/services/Game.js

'use strict';

app.factory('Game',
  function ($firebase, FIREBASE_URL) {
  var ref = new Firebase(FIREBASE_URL + 'games');

  var games = $firebase(ref);

  var Game = {
    all: games,
    create: function(game) {
      return games.$add(game);
    },
    find: function(gameId) {
      return games.$child(gameId);
    },
    delete: function(gameId) {
      return games.$remove(gameId);
    },

    addProp: function(gameId, prop) {
      prop.gameId = gameId;

      games.$child(gameId).$child('props').$add(prop);
    },
    deleteProp: function(game, prop, propId) {
      game.$child('props').$remove(propId);
    },

    addOption: function(propId, option) {
      option.propId = propId;

      games.$child(propId).$child('options').$add(option);
    }

    // addPropOption: function()
  };

  return Game;
});

/views/showgame.html

<div>
  <strong>{{ game.home }}</strong>
  <span class="vs">vs</span>
  <strong>{{ game.away }} </strong>
  <div ng-repeat="(propId, prop) in game.props">
    <span>{{ prop.text }}</span>
    <button ng-click="deleteProp(game,propId)" type="button" class="btn btn-danger">Delete Prop</button>
  </div><!--
  <button type="button" class="btn btn-danger" ng-click="deleteGame(gameId)">Delete Game</button> -->
  <div ng-rpeat="optionId, option) in prop.options">
    <span>{{ option.text }}</span>
  </div>
</div>

<form ng-submit="addProp()">
  <textarea ng-model="prop.text" placeholder="Enter Prop Here" class="form-control"></textarea>
  <input type="submit" value="Add Prop" class="btn btn-primary" />
</form>

<form ng-submit="addOption()">
  <textarea ng-model="option.text" placeholder="Enter Prop Option Here" class="form-control"></textarea>
  <input type="submit" value="Add Option" class="btn btn-primary" />
</form>
<a href="#/games">Back to Games</a>

For what it's worth, I"m a front end developer but I haven't used any Javascript framekworks before a couple weeks ago when I worked through a couple of the tutorials on www.thinkster.io (great stuff btw).

1 Answer 1

1

According to the Angular guide for controllers, you should:

Use controllers to:

  • Set up the initial state of the $scope object.
  • Add behavior to the $scope object.

NOT use controllers to:

  • Manipulate DOM — Controllers should contain only business logic. Putting any presentation logic into Controllers significantly affects its testability. Angular has databinding for most cases and directives to encapsulate manual DOM manipulation.
  • Format input — Use angular form controls instead.
  • Filter output — Use angular filters instead.
  • Share code or state across controllers — Use angular services instead.
  • Manage the life-cycle of other components (for example, to create service instances).

Thus, for any sophisticated app, most of the things you've discussed above belong in a service/factory. Your controller should handle only taking the data from those services and applying it to $scope (and providing any convenience methods to the DOM for interacting with services).

Sign up to request clarification or add additional context in comments.

2 Comments

Ah I see, thanks for clearing that up @Kato. As a follow up, what's the best way to structure the data for the game, props, prop options, etc. Is it a bad practice in Firebase to set up the data where the result of the prop would be somewhere like league.game.propId.answer? It seems like there would be a huge tree of child nodes expanding pretty far out.
For data structures, check out denoralization is normal and sql queries in Firebase

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.