2016-03-31 1 views
10

Обычный пример использования со списками - это доступ к методу списка из элемента списка. Например: у элемента проекта есть возможность удалить себя из содержащего списка. Я хотел бы знать, является ли шаблон, который я описываю ниже для Aurelia, действителен или, может быть, есть лучшие решения.Aurelia: доступ к родительскому методу VM изнутри дочернего ВМ

В Aurelia У меня есть следующие настройки:

Содержащий список: (проект-list.html и projectList.js)

<template>  
    <div class="projects"> 
    <input value.bind="newProjectName" placeholder="New project name"/> 
    <project-item repeat.for="project of projects" project.bind="project"></project-item> 
    </div> 
</template> 

и дочерний элемент (проект-пункт и ProjectItem. JS)

<template> 
    <span class="title"> 
    ${project.name} <i click.delegate="deleteProject(project)" class="icon-trash"></i> 
    </span> 
</template> 

В этом случае deleteProject(project) является членом projectList VM:

function deleteProject(project){ 
    var index = this.projects.indexOf(project); 
    if (index>-1){ 
     this.projects.splice(index,1) 
    } 
} 

К сожалению, как я понимаю из этого номера https://github.com/aurelia/framework/issues/311, , что wil не работает (больше).

В обходного я могу связать функцию по проекту повестки дня VM:

@bindable delete: Function; 

и в шаблоне проекта-лист:

<project-item repeat.for="project of projects" project.bind="project" delete.bind="deleteProject"></project-item> 

Это делает работу, обеспечить связанный функция является назначенным имуществом с закрытием:

deleteProject = function(project : Projects.Project){ 
     var index = this.projects.indexOf(project); 
     if (index>-1){ 
      _.remove(this.projects,(v,i)=>i==index); 
     } 
    } 

Закрытие необходимо для доступа к правильному контексту (this является списком проектов). Использование

function deleteProject(project) 

this будет относиться к контексту проекта повестки дня.

Даже если эта конструкция работает и не имеет много накладных расходов в сантехнике, он чувствует ко мне немного хрупкому:

  • назначенная функция трудно отличить, образует регулярную функцию класса
  • связывания функции как так как элемент списка кажется немного «переутомленным»

Возможно, мне не хватает механизма барботирования Aurelia, который обеспечивает доступ к родительской виртуальной машине, обрабатываемой каркасом?

Редактировать после ответа: на основе ответа по @Sylvain я сделал GistRun, реализующую реализацию списка скелета и элемент списка с добавлением и удаление:

Aurelia Skeleton list list-item implementation

ответ

10

Вот несколько альтернатив передать ссылку на функцию:

  • Попросите ребенка компонент транслировать общественное событие, используя одноэлементный экземпляр EventAggregator и иметь родительский компонент г Eact к событию

  • иметь ребенок компоненты трансляции личное события, используя частный EventAggregator экземпляр и есть родительский компонент реагирует на событие

  • иметь ребенок компоненты транслировать событие DOM и привязать его к родителю с delete.call как это <project-item repeat.for="project of projects" project.bind="project" delete.call="deleteProject($even t)"></project-item>

Моих личными предпочтениями является третьим вариантом. Это больше похоже на «веб-компоненты» для меня.

+0

Я использую третий вариант. Но учтите, что если у вас есть 'delete.call =" deleteProject (projectParam) "', вам нужно вызвать его из 'project-item', например' this.delete ({projectParam: this.project}) ' – valichek

+0

Третий вариант, используя '.call' привязка определенно то, что искал. Тем не менее, я все еще борюсь с параметром. @Sylvain: вы используете '$ event' в своем ответе. Это работает, и 'deleteProject' вызывается с проектом в качестве параметра. Также 'delete.call =" deleteProject (project) "" приводит к правильному вызову. Не могли бы вы объяснить, что означает параметр $ event в этом контексте? – Arjan

+0

@valichek: Я предполагал, что «назовите его из объекта проекта», который вы подразумеваете под классом viewmodel. Я попробовал ваше предложение, но я не могу заставить его работать. Я попытался: 'function doDelete() {this.delete (this.project); } 'в классе' projectItem'. Но 'this.delete' не определено. Итак, я думаю, это не то, что вы намеревались? – Arjan