2016-05-17 2 views
1

Как видно из заголовка, я пытаюсь связать источник элементов с вычисленным массивом, который заполняется результатами вызова http.fetch. Вот код (интересные части для этого вопроса):Aurelia - привязка repeat.for к вычисленному массиву, заполненному вызовом сервера

Вид:

<tr> 
    <td repeat.for="boardItemFilter of boardItemFilters"> 
     <input if.bind="boardItemFilter.isStringFilter()" type="text" value.bind="boardItemFilter.Value & debounce:400" /> 
     <div if.bind="boardItemFilter.isCheckboxFilter()" repeat.for="sourceValue of boardItemFilter.SourceValues"> 
      <input type="checkbox" value.bind="sourceValue" checked.bind="boardItemFilter.SelectedValues" /> 
      <span textcontent.bind="sourceValue"></span> 
     </div> 
    </td> 
</tr> 

модели представления:

@computedFrom('selectedUnit') 
get boardItemFilters(){ 
    let unitName = ""; 
    if(this.selectedUnit != null){ 
     unitName = this.selectedUnit.Name; 
    } 
    return this.datacontext.fetchBoardItemFiltersByUnit(unitName) 
    .then(result => console.log(result); 
} 

Если функция fetchBoardItemFiltersByUnit() является:

fetchBoardItemFiltersByUnit(unitName){ 
    let self = this; 
    let request = {'unitName': unitName}; 
    return this.http.fetch('BoardFilters',{ 
     method: 'post', 
     body: json(request), 
    }).then(response => response.json()) 
     .then(response => this.ExtendFilters(response)); 
} 

Выбранные триггеры boardItemFilters() на выбранномUnit изменяются правильно. Вызов datacontext сделан, эта часть работает отлично. Проблема возникает, когда aurelia пытается связать свойство до того, как будет выполнена http.fetch. Затем он думает, что свойство не повторяется и ломается. После этих ошибок console.log(result) отображает ожидаемый массив объектов, возвращаемых сервером, но результат не присваивается вычисленному свойству. Я попытался вручную повторить привязку, используя поведение сигнала, без везения.

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

Я пробовал много вещей, и единственное, что, казалось бы, работало, - создать локальную переменную, которая хранит результаты http, и всегда возвращать эту переменную OUTSIDE функции обещания. Но, естественно, это всегда будет возвращать предыдущее состояние, так как оно будет запускать асинхронный вызов и вернуть локальную переменную до завершения вызова. Это, конечно, неприемлемо.

Или Aurelia просто не поддерживает привязку асинхронного соединения?

Спасибо заранее!

EDIT: Мне удалось взломать решение, но оно довольно уродливое (используя привязкуSignaler в функции обещания для переподготовки, используя сравнение newValue и oldValue, чтобы избежать бесконечных вычисленных вызовов и т. Д.). Мне все равно хотелось бы услышать правильный способ добиться этого!

+0

вы пытаетесь сделать вызов HTTP в каждой итерации 'repeat.for', который, безусловно, не хороший подход, на мой взгляд. Вы должны переписать весь алгоритм. Кроме того, для привязки вычисленных свойств вам не нужно использовать скобки, это 'if.bind =" boardItemFilter.isStringFilter "достаточно –

+0

Я? У меня создалось впечатление, что я буду заполнять массив один раз, а затем просто перебираю его с помощью repeat.for .. не могли бы вы объяснить, пожалуйста? EDIT: я просто посмотрел на сетевой трафик, api вызывается только один раз, а не для каждой итерации. – HotTowelie

+0

О, и isStringFilter() - это функция, с которой я расширил объект фильтра, поэтому нужны скобки. .Я мог бы преобразовать его в вычисленное свойство, но имел бы смысл. Спасибо :) – HotTowelie

ответ

3

Вот способ решения такого рода длительных вычисленных операций, которые не полагаются на асинхронном связывания:

  • Изменения зависимого свойства от вычисленного для нормальной собственности.
  • Вручную обратите внимание на зависимости, чтобы вызвать длительную операцию. Только после завершения длительной операции обновите зависимое свойство.

Пример:

export class App { 
    @bindable count; 

    constructor() { 
    this.count = 3; 
    this.computeNums(this.count) 
     .then(result => this.nums = result); 
    } 

    countChanged(value) { 
    this.computeNums(value) 
     .then(result => this.nums = result); 
    } 

    computeNums(count) { 
    let result = []; 
    for (let i = 1; i <= count; i++) { 
     result.push(i); 
    } 

    return new Promise((resolve, reject) => { 
     setTimeout(() => resolve(result), 1000); 
    }); 
    } 
} 

Здесь nums вычисляется из count. computeNums имитирует длительную операцию.

Наблюдение count достигается комбинацией @bindable и countChanged. Вместо этого вы можете использовать API-интерфейс привязки, как в этом question.

Полный пример, который может работать: https://gist.run/?id=f2e26044796bfe2334d786554039aab0

+0

Я не знал о комбинации @bindable - countChanged. Спасибо, это прекрасно работает для этого случая. – HotTowelie

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