• Как передать с сервера (node.js) объект вместе с методами (function)?

    pofigizm
    @pofigizm Автор вопроса
    Правильный вариант получить на сервере и на клиенте одинаковые объекты с одинаковыми методами без двойного кода - это описать класс в отдельном файле и подключать его и на сервер и на клиенте. Единственное в чем была проблема (для меня) это как "назначить классы" объектам распарсенных из json. Назначать методы глобальному Object (т.к. он является прототипом объектов из JSON.parse()) не очень хотелось. Собственно код:

    Часть файла object.js
    ...
    function Order(object) {
      object.parts = object.parts || [];
      var partsArr = [];
      object.parts.forEach(function (value, key) {
        partsArr[key] = new Order(value);
      });
    
      this.name = object.name || 'Default';
      this.cost = object.cost || 0;
      this.parts = partsArr;
    }
    
    Order.prototype.summ = function() {
      var summ = 0;
      this.parts.forEach(function(part) {
        summ += part.summ();
      });
      return summ + this.cost;
    };
    ...

    подключаем на сервере и используем:
    ...
    var Order = require('./order')
    
    var myobject = new Order({name:'my object', cost: 10});
    myobject.parts[0] = new Order({name:'my first part', cost: 20});
    myobject.parts[1] = new Order({name:'my second part', cost: 30});
    myobject.parts[1].parts[0] = new Order({name:'my first in second part', cost: 40});
    ...

    подключаем на клиенте и используем:
    ...
    <script src='order.js'></script>  // здесь теги 
    ...
    var xhrobj = JSON.parse(this.responseText);
    var myobject = new Order(xhrobj);
    ...

    Полные варианты файлов можно скачать на гитхабе в новой ветке.

    Интересно послушать комментарии насчет такой реализации.
    Ответ написан
    Комментировать
  • Как обрабатывать элементы при рекурсивном вызове "ng-repeat" ? (Исправлено)

    pofigizm
    @pofigizm Автор вопроса
    Можно добавить методов самим данным:
    // создаем конструктор "класса" и нужные методы
        function Order(name) {  
          this.name = name;
        }
        Order.prototype.addChild = function () {
          this.parts = this.parts || [];
          var levelName = this.name + '-' + (this.parts.length + 1);
          this.parts[this.parts.length] = new Order(levelName);
        };
        Order.prototype.removeChild = function (index) {
          if (index === undefined) {
            delete this.parts;
          } else if (index > -1 && index < this.parts.length) {
            this.parts.splice(index, 1);
            if (this.parts.length === 0) delete this.parts;
          }
        };
        
    //  имитация тех данных, которые приходят с сервера (в примере)
        var prepareOrders = [];
        prepareOrders[0] = new Order('part 1');
        prepareOrders[0]['_id'] = '123456';
        prepareOrders[1] = new Order('part 2');
        prepareOrders[1]['_id'] = '234567';
    
    // Вставляем в $scope
        $scope.orders = prepareOrders;

    и затем в вызовах ng-click можно обращаться к методам этих "объектов" и "под-объектов":
    <a href='' ng-click='$parent.$parent.part.removeChild($index)'>Remove this</a>
    <a href='' ng-click='part.addChild()'>Add child</a>
    <a href='' ng-click='part.removeChild()'>Remove childs</a>


    Вот так это работает:
    embed.plnkr.co/DHEbQeyxySjOhk5kdlLh/preview

    Как Вам такой вариант? Мне он больше нравится, т.к. эти методы вообще с сервера получать можно.
    Ответ написан
    Комментировать
  • Ng-repeat во втором уровне json

    pofigizm
    @pofigizm
    Ответ написан
    Комментировать
  • Как задержать построение документа или обработку директивы до получения данных с сервера?

    pofigizm
    @pofigizm Автор вопроса
    Есть конечно один вариант с помощью таймера:
    // ...
            link: function (scope, element) {
              setTimeout(function () {
                var html = '';
                angular.forEach(scope.orders, function (ord) {
                  html += '<h4>' + ord.name + '</h4>';
                });
                element.append($compile(html)(scope));
                console.log('end of directive');
              }, 1000);
            }
    // ...

    Также можно внутри таймера проверять если данные пришли то выполнять, если нет то еще подождать.
    Может быть есть более изящное решение?

    ++ еще через 1 час...

    Нашел вариант который меня в принципе устраивает:
    // ...
      .directive('orderDrct', ['$compile', 'Order',
        function ($compile, Order) {
          return {
            restrict: 'A',
            link: function (scope, element) {
              Order.query({id: 'all'}, function(orders) {
                scope.orders = orders;
                var html = '';
                angular.forEach(scope.orders, function (ord) {
                  html += '<h4>' + ord.name + '</h4>';
                });
                element.append($compile(html)(scope));
              });
            }
          };
        }
      ])
    // ...


    т.е. перенести запрос к серверу в функцию линковки и в его коллбеке уже выполнить код.

    Есть еще варианты?
    Ответ написан
    Комментировать
  • Изменить моментальное изменение значения в модели Angular

    pofigizm
    @pofigizm
    Есть директива ng-Focus которая может вызвать таймер или еще чего-нибудь.
    К сожалению нету события потери фокуса, поэтому тоже велосипед.
    Ответ написан
    Комментировать
  • Документация на $resourceProvider, в частности стандартные .get и .save

    pofigizm
    @pofigizm Автор вопроса
    На stackoverflow.com ткнули носом на то место в доках где это указанно:

    Методы принимают следующие параметры:

    HTTP GET "class" actions: Resource.action([parameters], [success], [error])
    non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
    non-GET instance actions: instance.$action([parameters], [success], [error])

    Success вызывается с (value, responseHeaders) аргументами.
    Error вызывается с (httpResponse) аргументом.
    Ответ написан
    Комментировать