2013-11-14 4 views
8

Я пытаюсь выяснить, какой правильный способ Ember.js моделировать этот проект будет, например. какие модели, маршруты и контроллеры понадобятся. I have started a jsBin to work from.Ember.js: как смоделировать этот пример?

Мои требования можно смело уменьшить до:

Элементы & их варианты

  • изделия имеют набор опций
  • Опции имеют свои собственные свойства
  • Детали имеют другие свойства (рядом с опциями), что приборная панель будет использовать

Dashboard

  • Приборная панель не имеет никаких данных о его собственного
  • Приборная панель необходимо соблюдать все детали и опции, а также обновить анализ их свойств

навигации

  • Vi rtual none
  • Это будет отображаться на одной странице, но в будущем может быть добавлено небольшое количество страниц/всплывающих окон
  • Я хочу, чтобы иметь возможность сохранять и повторно заполнять заданное состояние (например, список выбранных Опция идентификаторы)

данные

  • данные будут загружены один раз с одним вызовом JSon
  • логика
  • приложений будет сделан исключительно в Ember на клиентской стороне - нет Аякса для бизнес-логики
  • только последующий контакт ж/сервер будет, если/когда пользователь сохраняет состояние

Так как бы это быть структурирована в Эмбер?

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

jsBin Макета (link)

Я создал ряд шаблонов руля, но не принял удар на то, что должны существовать модели и какие контроллеры необходимы. Screenshot of jsBin mockup

Json

{ 
    "Items" : [ 
    { 
     "Item" : { 
     "nid" : "3", 
     "title" : "Hydro", 
     "image" : "http://bpf.vm/sites/default/files/bpf_things/hydro.jpg", 
     "properties" : "Baseload, Intermittent", 
       "values" : { 
        "Cost" : { 
         "price" : "6", 
         "quantity" : null 
        }, 
        "Percent of Portfolio" : { 
         "price" : null, 
         "quantity" : "56" 
        } 
       }, 
       "options" : { 
        "1" : { 
         "price" : "1512", 
         "quantity" : "10000" 
        }, 
        "12" : { 
         "price" : "825", 
         "quantity" : "20000" 
        }, 
        "11" : { 
         "price" : "550", 
         "quantity" : "50000" 
        } 
       } 
     } 
    }, 
    { 
     "Item" : { 
     "nid" : "4", 
     "title" : "Nuclear", 
     "image" : "http://bpf.vm/sites/default/files/bpf_things/nuclear.jpg", 
     "id" : "", 
     "properties" : "Baseload, Predictable", 
       "values" : { 
        "Cost" : { 
         "price" : "8", 
         "quantity" : null 
        }, 
        "Percent of Portfolio" : { 
         "price" : null, 
         "quantity" : "21" 
        } 
       }, 
       "options" : { 
        "4" : { 
         "price" : "825", 
         "quantity" : "10000" 
        }, 
        "13" : { 
         "price" : "411", 
         "quantity" : "15000" 
        } 
       } 
     } 
    }, 
    { 
     "Item" : { 
     "nid" : "5", 
     "title" : "Natural Gas", 
     "image" : "http://bpf.vm/sites/default/files/bpf_things/gas.jpg", 
     "id" : "9", 
     "properties" : "Baseload, Predictable", 
       "values" : { 
        "Cost" : { 
         "price" : "5", 
         "quantity" : null 
        }, 
        "Percent of Portfolio" : { 
         "price" : null, 
         "quantity" : "24" 
        } 
       }, 
       "options" : { 
        "7" : { 
         "price" : "400", 
         "quantity" : "50000" 
        }, 
        "10" : { 
         "price" : "600", 
         "quantity" : "100000" 
        } 
       } 
     } 
    } 
    ] 
} 
+0

Можете ли вы уточнить, что вы подразумеваете под моделированием этого? Вы имеете в виду, как вы проектируете контроллеры, URL-адреса и т. Д.? Или вы имеете в виду модели данных? Если первое, увидев вашу «уродливую» настройку, будет полезно. – EmptyArsenal

+0

Обновлено сообщение w/more details, ссылки на jsBin (только шаблоны - проблема с переносом моей текущей работы) и обновленный снимок экрана. – doub1ejack

+0

очень полезная беседа о том, как структурировать это приложение с Конрадом: http://chat.stackoverflow.com/rooms/41721/discussion-between-conrad-friedrich-and-doub1ejack – doub1ejack

ответ

2

Вот зачатки ответ:

Модели

Я думаю, что нужно только три модели здесь. Панель инструментов является основным игроком в этом приложении, но у нее нет никаких данных.

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

Контроллеры

Раньше я полностью отсутствовал в концепции ArrayControllers. Как правило, для чего-либо, что является коллекцией, потребуется ArrayController для его представления, а не простой элемент управления ObjectController. Мои «Элементы» будут нужны, но я не думаю, что «Параметры» будут, потому что «Параметры» являются дочерними элементами Item и могут использовать Item/Items в качестве прокси.

  • Dashboard - Я предполагаю, что это собирается быть мускулистый один, так как контроллер должен обработать все пункты & коллекции
  • Элементы - так как есть много пунктов, мы будем нуждаться в ArrayController для них
  • Пункт - элемент должен сделать некоторый простой анализ это варианты, когда их состояние изменяется
  • вариант - варианты будут, как минимум, должны реагировать на кнопку действия

Шаблоны

Углубление здесь представляет шаблоны, которые делают другие шаблоны. Например, мой шаблон отображения содержит {{render dashboard}} и {{render items}}.

  • Применение - технически корень приложения, он перенаправляет на дисплей (который, вероятно, нет необходимости)
    • Display - по существу, корень моего приложения.
      • Панель - область, которая обеспечивает визуальный анализ Items/Опции
      • Элементы - оказывает каждому пункту
        • Варианты - предоставляет опции для каждого элемента

Маршруты

Это все еще очень туманно. Маршруты, похоже, играют много ролей (сопоставление URL-адресов с моделями, настройка моделей для контроллеров, может быть, другие вещи?). На данный момент только URL, я могу думать о необходимости является:

  • Дисплей - так как мой «дисплей» представляет собой снимок приложения (например, сохраненная версия), он должен быть указан в App.Router. карта

Другие маршруты:

  • ApplicationRoute
    • setupController: устанавливает контроллер, пустой/сохраненным дисплей
  • IndexRoute
    • redirect: просто перенаправляет на маршрут дисплея (по существу корень приложения)
  • DisplayRoute
    • model: устанавливает данный дисплей в качестве модели
    • afterModel: загрузите предметы, указанные на дисплее

Я думаю, что это все. Это простое приложение, и как только у меня есть элементы, загруженные для Дисплея, приложение просто изменяет отображение экрана. Есть выбор пользователя, но они являются булевыми флагами (например, параметр isSelected on Item должен изменять данные, отображаемые информационной панелью) - эти выборы не требуют никакой навигации.

+0

Одна из проблем, которые я вижу здесь, это то, что я не очень используя концепцию коллекции предметов. До сих пор я только думал о том, чтобы использовать {{each}} для их рендеринга и вообще не рассматривал маршрутизацию для коллекции элементов. – doub1ejack

3

Я поставил небольшую JSBin http://jsbin.com/IdAXuMar/5/edit

Хорошо, так после того, как чат и немного дольше смотреть на него, вот мои мысли о том, как упростить это:

У вас есть только один URL, поэтому я бы пошел только с одним Маршрутом и одним контроллером.

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

Дисплей имеет много товары, Пункт имеет много Опции

И потому, что вы только когда-либо смотреть на один дисплей за раз, вам не нужно отображать как модель вообще. Если ваше приложение развивается, и у вас одновременно есть несколько Дисплеев, имеет смысл реализовать модель дисплея, и делать все запросы JSON через эту модель.

Я бы реализовать один маршрут и контроллер:

App.Router.map(function() { 
    this.resource('display', path: { 'display/:id' }); 
}); 

App.DisplayRoute = Ember.Route.extend({ 
    model: function(params) { 
     return App.Item.find(params._id); 
    } 
}); 

DisplayController имеет полный доступ на все это предметы, так как они установлены, как это модель.

Думаю, вам нужен только один шаблон, теперь вы можете разделить их на несколько частей, если они выходят из-под контроля.

<script type="text/x-handlebars" data-template-name="display">  
    {{#each model}} 
    <!-- access on every item here --> 


    {{#each option}} 
     {{#if isSelected}} 
     this option is selected 
     {{/if}} 
     <!-- access on every option here --> 

     <a {{action selectOption this}} href=''> Select this option</a> 

    {{/each}} 
    {{/each}} 
</script> 

Обратите внимание на selectOption действие: при вызове этого и передавая параметр, вы можете установить выбранное состояние непосредственно на сам вариант, который будет немедленно отражать в представлении.

App.DisplayController = Ember.ArrayController.extend({ 
    // add computed properties here.. 

    actions: { 
     selectOption: function(option) { 
      option.set('isSelected', true); 
     } 
    } 

}); 

Чтобы получить детали с сервера, вы могли бы назвать App.Item.find(), а затем передать идентификатор дисплея. Это не 100% условно, так как вам следовало бы передать идентификатор Item здесь, но я думаю, что для этого все в порядке. так что этот метод будет выглядеть примерно так

App.Item = Ember.Option.extend({ 
    selected: false 
    // add computed properties here 
}); 

App.Item.reopenClass({ 

    // retrieves the items from the server 

    find: function(displayId) { 

     var url = "/game/json" + displayId; 

     var items = new Ember.A(); 

     Ember.$.getJSON().success(function(data) { 
      data.items.forEach(function(jsonItem) { 

       var item = Ember.Item.create({ 
        nid: jsonItem.nid, 
        title: jsonItem.title, 
        image: jsonItem.image 
       }); 

       item.set('options', new Ember.A()); 

       jsonItem.options.forEach(function(option) { 
        var option = Ember.Option.create({ 
         // set option properties 
        }); 
        emberItem.get('options').pushObject(option); 
       }) 

      }) 

     }); 

     return items; 
    } 
}); 

Я надеюсь, что поможет вам начать работу, и, возможно, делает его немного легче перенести концепцию Эмбер. Если у вас есть вопросы относительно, например, как сохранить все обратно на сервер, стреляйте :)

Смежные вопросы