Daj Się Poznać #4 OOP. Model w AngularJS


W poprzednich częściach projektu Mistrz Makro, pisanego w AngularJS stworzyliśmy wstępny szablon projektu, wyjaśniliśmy jak korzystać z Gita, zrozumieliśmy czym jest i do czego służy JSON, dowiedzieliśmy się co to MVC i zaimplementowaliśmy kontroler oraz serwis, które pozwoliły wyświetlić nam odebrane z JSON dane w konsoli. W dzisiejszej, czwartej już części, skupimy się na tym żeby umieścić nasze dane w modelu, żeby w kolejnej części dyrektywa tworząca quiz mogła z nich swobodnie korzystać. Zaczynajmy!

Jeśli pobrałeś już moje repozytorium z Githuba, co opisałem w poprzednim poście to możesz teraz przeskoczyć do kolejnego commita, który pokaże Ci kod z tego posta:
$ git checkout 1b3cb2d8eee6994d93ad28fd3f6ce037b0b6a771

# Tworzymy model dla makroskładników

AngularJS to framework MVC, czyli Model, Widok oraz Kontroler. Zajmiemy się tym razem Modelem, czyli przechowywaniem danych aplikacji. Na początek, musimy stworzyć serwis, w którym będzie zapisany pojedyńczy produkt:

 
(function() {
  'use strict';

  angular
    .module('quizProject')
    .service('Macro', MacroModel);

  function MacroModel() {

    var Macro = function(id, name, kcal, protein, carb, fat, img) {
      this.id = id || 0;
      this.name = "";
      this.kcal = kcal || 0;
      this.protein = protein || 0;
      this.carb = carb || 0;
      this.fat = fat || 0;
      this.img = img || "";
    }

    Macro.prototype = {
      setId: function(id) {
        this.id = id;
      },

      setName: function(name) {
        this.name = name;
      },

      setKcal: function(kcal) {
        this.kcal = kcal;
      },

      setProtein: function(protein) {
        this.protein = protein;
      },

      setCarb: function(carb) {
        this.carb = carb;
      },

      setFat: function(fat) {
        this.fat = fat;
      },

      setImg: function(img) {
        this.img = img;
      },
  
    };
    return Macro;
  }
})();

Na wzór klasy tworzymy funkcję prototypową, która posiada takie parametry jak id, name, kcal, protein, carb, fat, img i nadaje im wartości domyślne:

 
var Macro = function(id, name, kcal, protein, carb, fat, img) {
  this.id = id || 0;
  this.name = "";
  this.kcal = kcal || 0;
  this.protein = protein || 0;
  this.carb = carb || 0;
  this.fat = fat || 0;
  this.img = img || "";
}

Wszystkie te parametry odpowiadają tym z naszego pliku answers.json:

 
{
"questions":[
    {
      "id": "1",
      "name": "bułka",
      "kcal": 600,
      "protein": 30,
      "carb": 60,
      "fat": 6,
      "img": "img1.jpg"
    },
    {
      "id": "2",
      "name": "pizza",
      "kcal": 900,
      "protein": 20,
      "carb": 80,
      "fat": 20,
      "img": "img2.jpg"
    }
  ]
}

Do prototypu tej funkcji, dodajemy funkcje, które będą dostępne w każdym utworzonym obiekcie. Dzięki nim, będziemy mogli przypisać nasze dane pobrane z serwisu do odpowiednich parametrów. Rozbiliśmy to na kilka pomniejszych funkcji, które pobrany parametr przypisują do zmiennej aktualnego obiektu, co wskazuje this.:

 
Macro.prototype = {
  setId: function(id) {
    this.id = id;
  },

  setName: function(name) {
    this.name = name;
  },

  setKcal: function(kcal) {
    this.kcal = kcal;
  },

  setProtein: function(protein) {
    this.protein = protein;
  },

  setCarb: function(carb) {
    this.carb = carb;
  },

  setFat: function(fat) {
    this.fat = fat;
  },

  setImg: function(img) {
    this.img = img;
  },

};

# Tworzymy model dla produktów

Kolejnym krokiem będzie stworzenie drugiego modelu, który będzie pełnił rolę listy obiektów z modelu makroskładników.

 
(function() {
  'use strict';

  angular
    .module('quizProject')
    .service('ProductModel', ProductModel);

  function ProductModel() {
    var _list = [];

    return {
      addItem: function(model) {
        return _list.push(model);
      },

      listOfItems: function(){
        return _list;
      },

    }
  }
})();

Serwis, który widzimy posiada prywatną tablicę, na której manipulacje możemy wykonywać za pomocą utworzonych metod. W tym przypadku jest to addItem oraz listOfItems. W pierwszym przypadku, addItem pozwala dodać obiekt stworzony przez MacroModel do tablicy. listOfItems zwraca nam całą listę aktualnych obiektów.

# Kontroler czyli łączymy modele oraz serwis

Nasz kontroler z poprzedniego posta po drobnych modyfikacjach, wygląda w taki sposób:

 
(function() {
  'use strict';

  angular
    .module('quizProject')
    .controller('MainController', MainController);

  function MainController($scope, GetJson, $http, Macro, ProductModel) {

    var promiseAnswers = GetJson.getData();

    var Model = new Macro();
    $scope.Model = Model;
        
    promiseAnswers.then(function(data){
      data.questions.forEach(function(answer) {
        $scope.Model.setId(answer.id);
        $scope.Model.setName(answer.name);
        $scope.Model.setKcal(answer.kcal);
        $scope.Model.setProtein(answer.protein);
        $scope.Model.setCarb(answer.carb);
        $scope.Model.setFat(answer.fat);
        $scope.Model.setImg(answer.img);

        ProductModel.addItem($scope.Model);
        console.log(ProductModel.listOfItems());
        $scope.Model = new Macro();
      });
    });

  };
})();

Na początku zaczynamy od wstrzykiwania zależności, które opisywałem w poprzedniej cześci. Dzięki temu zabiegowi, będziemy mogli odwoływać się do naszych modeli z poziomu kontrolera.

 
function MainController($scope, GetJson, $http, Macro, ProductModel) {

Dodaliśmy Macro oraz ProductModel, czyli nazwy serwisów, dzięki czemu możemy teraz wykonać operację new Macro();:

 
  var Model = new Macro();
  $scope.Model = Model;

W ten sposób tworzymy nowy obiekt dla makroskładników jednego z produktów i nazywamy go Model.

 
promiseAnswers.then(function(data){
  data.questions.forEach(function(answer) {
    $scope.Model.setId(answer.id);
    $scope.Model.setName(answer.name);
    $scope.Model.setKcal(answer.kcal);
    $scope.Model.setProtein(answer.protein);
    $scope.Model.setCarb(answer.carb);
    $scope.Model.setFat(answer.fat);
    $scope.Model.setImg(answer.img);

    ProductModel.addItem($scope.Model);
    console.log(ProductModel.listOfItems());
    $scope.Model = new Macro();
  });
});

Nasza funkcja z poprzedniego posta, która pozwoliła wyświetlić promise, wysłany z serwisu GetJson jest teraz zmieniona w taki sposób, żeby odebrane dane dodawać do obiektu model. Odwołujemy się do Modelu i jego metod takich jak setId.

 
  ProductModel.addItem($scope.Model);
  console.log(ProductModel.listOfItems());
  $scope.Model = new Macro();

Następnie dodajemy model do tablicy obiektów znajdującej się w ProductModel za pomocą metody addItem. Wyświetlamy całość listy obiektów i ponownie tworzymy nowy obiekt, który wypełnimy kolejnymi danymi.

widok konsoli

W taki sposób powinna wyglądać konsola po uruchomieniu aplikacji. Wyświetlona jest tablica zawierająca dwa obiekty, których każdy parametr odpowiada tym z answers.json.

Published: April 09 2017

blog comments powered by Disqus