Ресурс Angular — структура модели по умолчанию

Поэтому я использую этот Rest API с ngResource для выполнения запросов get, query, post и update. Я ищу способ определить структуру для каждой сущности.

Например, предположим, что у нас есть:

module.factory('app.entity.item', function($resource) {
    return $resource('http://xmpl.io/items/:itemId', { itemId: '@id' });
});

Я хочу создать экземпляр в контроллере, например:

module.controller('AddItemCtrl', ['app.entity.item', function(Item) {
    $scope.item = new Item();
});

и привяжите его к соответствующей форме в моем шаблоне.

Фактическая проблема, с которой я столкнулся, заключается в том, что мне приходится иметь дело с таблицами 1:m. Примером структуры сущности может быть:

{
  "name": "",
  "categories": [],

  "list": [
    {
      "value": "",
      "list": [
        {
          "value": "",
          "list": [
            {
              "value": ""
            }
          ]
        }
      ]
    }
  ]
}

(более подробный пример в скрипте ниже)

Теперь первые два поля явно не проблема. Это третий. list. Каждый из этих списков может иметь переменное количество элементов.

В настоящее время я использую ngRepeat и метод add(type, context), который добавляет новый набор полей в область (поле value в этом примере и дочерние списки для первых двух уровней), которые будут отображаться в пользовательском интерфейсе с помощью ngRepeat, чтобы пользователь мог его заполнить. и отправьте в сервис.

Во-первых, я должен определить структуру, чтобы пользовательский интерфейс не был пустым при загрузке страницы.

module.controller('AddItemCtrl', ['app.entity.item', function(Item) {
    $scope.item = new Item({
      "name": "",
      "categories": [],

      "list": [
        {
          "value": "",
          "list": [
            {
              "value": "",
              "list": [
                {
                  "value": ""
                }
              ]
            }
          ]
        }
      ]
    });
});

Но это лишнее. Я должен сделать это везде! Другая проблема заключается в том, что при вызове item.$save модель очищается (возможно, повторно создается экземпляр?), а поля внутри свойства списка (управляемые директивой ngRepeat) исчезают.

Поэтому мне интересно, что бы вы сделали в таких обстоятельствах. Есть ли способ определить структуру объекта (ресурса)?

ПРИМЕР: http://jsfiddle.net/g15sqd5s/3/


person Fardin K.    schedule 02.12.2014    source источник


Ответы (2)


пытаясь дать простой ответ - для простых структур я бы использовал что-то вроде

module.factory('Item', function($resource) {
  var resource = $resource('http://xmpl.io/items/:itemId', { itemId: '@id' },
    // you can also define transformRequest here: 
    { transformRequest: function(data) {
      // data can be transformed here
      return angular.toJson(data);
    }});

  return angular.extend(resource.prototype, 
    {
       name: null,
       categories: []
    });
  });

но затем помните о необходимости "выравнивать" объект.

а для более сложной модели я бы выбрал restangular

аналогичная тема также обсуждается здесь: Как я могу расширить конструктор ресурса AngularJS ($resource)?

person ciekawy    schedule 17.02.2015
comment
Я не понимаю, для чего используется transformRequest; и я не уверен в манипулировании прототипом, но это точно решение. +1 за это и ссылки. - person Fardin K.; 18.02.2015
comment
transformRequest просто показывает, что есть еще одна возможность справиться со сложными/нестандартными случаями. - person ciekawy; 18.02.2015
comment
Ага! Я знаю об этом, но не думаю, что это может быть решением в моем случае. - person Fardin K.; 18.02.2015

Я бы пошел дальше и в первую очередь пересмотрел структуру моей модели в бэкэнде - модели на стороне клиента должны просто следовать уже определенным, а не переопределяться в блоке преобразования. Итак, чтобы ответить на ваш вопрос, структура модели «по умолчанию» исходит от сервера. То, что вы получаете в своих объектах $resource, имеет структуру того, что возвращает ваш сервер.

Для начала, действительно ли можно вызывать $save для модели Item, когда пользователь заполнил некоторые значения? Очевидно, что мы хотим сохранить списки, связанные с элементом, а не сам элемент. Отдельный ресурс, определенный в бэкенде, скажем, items/<item_id>/list, может быть более чистым решением. Это может не очень хорошо масштабироваться, так как вам придется делать отдельный GET запрос для каждого элемента, чтобы получить его список, но это правильный способ RESTful сделать это.

Распространяя этот подход на пример в вашей скрипке, я думаю, что схема маршрутизации, такая как buildings/<building_id>/floors/<floor_id>/units/<unit_id>, была бы правильным решением. Отправив GET запрос buildings/, вы получите список зданий; каждое здание в возвращаемом массиве должно быть экземпляром модели Building, для которой задан правильный URL-адрес, чтобы пользователь мог выполнить одно POST и обновить только имя здания, вместо отправки всей структуры обратно на сервер. Применение этого рекурсивно к вложенным ресурсам должно дать вам чистый и лаконичный способ работы с изменениями модели.

Что касается части пользовательского интерфейса, я бы определил три директивы для зданий, этажей и юнитов, и пусть каждая из них управляет массивом с соответствующими ресурсами, а также позаботится о привязках пользовательского интерфейса к значениям модели.

Так как же может выглядеть модель Building?

var BuildingResource = $resource('/buildings/:id', { id: '@id' });

Вызов BuildingResource.query() должен дать массив существующих зданий. Добавление нового здания может выглядеть так:

var newBuilding = new BuildingResource();
newBuilding.$save().then(function(building) {
  $scope.buildings.push(building);
}, function(errData) {
  //Handle error here...
});

Этот шаблон должно быть легко распространить на остальные ресурсы — обратите внимание, что сервер должен возвращать для каждого здания только name и id; зная id, достаточно создать URL (и объект $resource соответственно) для получения необходимых дочерних ресурсов (в данном случае этажей).

person petkov.np    schedule 23.02.2015
comment
Модели не переопределяются. Я предоставляю пользователю форму для СОЗДАНИЯ объекта, который не существует. Я не считаю, что должен просить сервер о пустой модели! То, что вы сказали о правильном способе RESTful сделать это, совершенно правильно в случае с моим примером jsfiddle; но мы работаем с единым целым; плюс мы стараемся минимизировать запросы. Добро пожаловать, кстати. - person Fardin K.; 23.02.2015
comment
В моем примере нет ни одной точки, в которой у сервера запрашивается пустая модель. Второй фрагмент кода создает модель на стороне клиента, которая может содержать любые данные (например, имя). Затем ответ на запрос POST добавляется в массив области действия — он будет содержать действительный идентификатор, возвращенный из базы данных. Если вы работаете с одним объектом, что означает «1:m» в исходном запросе? Это означает, что поверх одной «базовой» сущности у вас будет массив сущностей. Именно для этого и предназначен предлагаемый подход. - person petkov.np; 23.02.2015
comment
Мое угловое приложение не заботится о том, как сервер обрабатывает свои модели; Он видит только одну сущность. (Предположим, что в данном случае это просто имеет смысл!) Я упомянул 1:m для того, чтобы читатели могли визуализировать структуру. Это было до того, как я добавил примеры. --- Предлагаемый подход не решает поставленной задачи. Я хочу создать форму. Я не понимаю, как разделение исходной сущности на иерархию других сущностей помогает решить эту проблему. - person Fardin K.; 23.02.2015
comment
Проблема не в обработке ресурсов, а в генерации форм вообще и, в частности, Entity Structure в resourceProvider API. - person Fardin K.; 23.02.2015
comment
Тогда, пожалуйста, измените свою скрипку. Прямо сейчас мы видим там кнопки добавления, которые добавляют сущности в массивы; нет упоминания о единой сущности и порождении формы. Я думаю, что скрипки должны служить цели представить соответствующий пример, иллюстрирующий проблему. - person petkov.np; 23.02.2015
comment
Вы можете предположить, что существует одна сущность или несколько сущностей; это не имеет отношения к вопросу. Моя жалоба на ваш ответ, который не имеет отношения к реальному вопросу! - person Fardin K.; 23.02.2015