Polymer и Polymerfire: как просмотреть данные от наблюдателя?

У меня есть простой тег <firebase-query>, и я хотел бы манипулировать некоторыми данными, прежде чем они будут отображаться с помощью <dom-repeat>. Например, мне нужно преобразовать некоторые поля в ссылки, а также разобрать некоторые даты.

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

Для этого у меня есть наблюдатель за данными, чтобы определить, когда они будут готовы. Однако я не могу понять, как перебрать данные из этой функции JavaScript. По какой-то причине for(var i in items) не работает, хотя элементы есть.

Вот компонент:

<dom-module id="cool-stuff">

  <template>

    <firebase-query id="query" path="/items" data="{{items}}"></firebase-query>

    <template is="dom-repeat" items="{{items}}" as="item">
      [[item.name]]<br />
      [[item.date]]<br />
    </template>

  </template>

  <script>
    Polymer({
      is: 'ix-table',
      properties: {
        items: {type: Object, observer: "_itemsChanged"},
      }
      itemsChanged: function(data) {
        // how do I loop through the data received from firebase-query?
        console.log(data);
      }
    });
  </script>

</dom-module>

В идеале все, что я хотел бы сделать в функции наблюдателя, это что-то вроде:

for(var i in data) {
  obj = data[i];
  obj.name = '<a href="/item/"+obj.key>'+ojb.name+'</a>';
}

Но я не могу перебирать данные в цикле.

Внутри функции наблюдателя console.log(data) возвращает некоторые странные вещи вроде этого:

Array[o]
0: Object (which contains a proper item)
1: Object (same)
2: Object (same)

Обновление:

Вот скриншот того, что возвращает console.log (data) (изнутри наблюдателя):

введите описание изображения здесь

Кажется, что массив заполнен всеми объектами, но отображается как Array [0]. Так что это не позволит мне пролистать их.

Обновление 2:

Благодаря arfost вот решение:

<script>
  Polymer({
    is: 'ix-table',
    properties: {
      items: {type: Object},

    }
    observers: [
      '_itemsChanged(items.splices)'
    ],
    _itemsChanged: function(changeRecord) {
      if (changeRecord) {
        changeRecord.indexSplices.forEach(function(s) {
          for (var i=0; i<s.addedCount; i++) {
            var index = s.index + i;
            var item = s.object[index];
            console.log('Item ' + item.name + ' added at index ' + index);
            // do whatever needed with the item here:
            this.items[index].name = "New name";
          }
        }, this);
      }
    },
  });
</script>

person Hubert    schedule 03.01.2017    source источник
comment
Хорошо, но я думаю, что вы ошиблись при вычислении индекса, почему вы добавляете к нему 1? индекс 0 совпадает с объектом 0 также для каждого уже пройденного цикла, зачем вам еще один цикл for.   -  person TheeBen    schedule 08.04.2017
comment
Честно говоря, я не очень разбираюсь в этом бизнесе сращивания ... все, что я знаю, это то, что этот фрагмент кода работает и позволяет мне получать элементы, возвращаемые Firebase.   -  person Hubert    schedule 09.04.2017
comment
Я думаю, вам не понадобится сращивание, если ваш путь заканчивается узлом, который имеет разветвленные узлы с вложенными дочерними элементами, но когда ваш путь заканчивается немедленными дочерними элементами, требуется сращивание. Но возьмите это с долей скепсиса.   -  person TheeBen    schedule 10.04.2017
comment
Не знаю, элегантное ли это решение, но вы, сэр, решили мою проблему. Спасибо!   -  person luckyging3r    schedule 21.06.2017


Ответы (3)


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

Это происходит из-за того, как запрос firebase получает массив, как работают наблюдатели полимеров, и скрывается тем фактом, что консоль javascript основана на ссылке, когда она показывает объекты.

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

Итак, ваша функция вызывается, как только массив создается, но по-прежнему пуст, и вы не можете выполнять итерацию, поскольку он пуст. Затем вы регистрируете его, где под-свойства примитивов отображаются правильно (массив [0])

Затем firebase начинает заполнять массив данными. Ссылка на массивы остается прежней, поэтому полимер больше не запускает наблюдателя, а в консоли, когда он пытается отобразить массив, он отображает массив, указанный в журнале, который теперь содержит данные.

Я рекомендую вам использовать наблюдатель мутации массива вместо вашего простого, как показано ниже.

`properties: {
    items: {type: Object},
  },
,
observers: [
       '_itemsChanged(items.splices)'
],`

Он будет срабатывать каждый раз, когда объект будет добавлен в ваш массив, и вы сможете выполнять необходимую работу :)

У меня была ссылка на документацию по наблюдателю мутации массива :) полимер наблюдатель мутации массива

Надеюсь, это решит вашу проблему, удачного дня.

person Arfost    schedule 04.01.2017
comment
Ах, круто, это было именно то решение! Большое спасибо за то, что указали в нужное место. Я обновил первый пост с решением. - person Hubert; 04.01.2017
comment
Я тоже сталкиваюсь с этим. Я не хочу действовать на каждом «соединении», а беру сразу весь набор данных, когда он закончит загрузку всех элементов. Как я могу это сделать? - person Riël; 07.04.2017
comment
Благодаря возможностям firebase в реальном времени у вас никогда не будет всего набора данных, так как в каждый момент может быть добавлен новый узел от других клиентов. Если вы хотите рассматривать его как единое целое, а не список независимых X элементов, firebase-document лучше подходит для этого, я думаю - person Arfost; 07.04.2017
comment
Да, если вам не нужно перебирать каждый элемент (что в моем случае я сделал), тогда это намного проще, и firebase-document будет более подходящим - person Hubert; 09.04.2017

<firebase-query> результаты

Обратите внимание, что <firebase-query> приводит к массиву объектов. Допустим, ваша база данных содержит следующие элементы под /notes/<USER_ID>/:

введите описание изображения здесь

Ваш <firebase-query> будет выглядеть примерно так:

<firebase-query
    id="query"
    app-name="notes"
    path="/notes/[[user.uid]]"
    data="{{notes}}">
</firebase-query>

(где user привязан к <firebase-auth>.user).

Предполагая, что пользователь вошел в систему, <firebase-query> затем заполнит свое свойство data (т. Е. Привязанное к notes) следующим массивом:

введите описание изображения здесь

Обратите внимание, как каждый объект содержит свойство $key, которое соответствует ключу элемента, отображаемому в представлении База данных консоли Firebase.

Затем вы можете выполнить итерацию notes напрямую с помощью <dom-repeat>:

<template is="dom-repeat" items="[[notes]]">
  <li>
    <div>key: [[item.$key]]</div>
    <div>body: [[item.body]]</div>
    <div>title: [[item.title]]</div>
  </li>
</template>

Привязка к строкам HTML

Вы должны знать, что привязки строковых данных в этом случае отображаются буквально, поэтому попытка установить name в obj.name = '<a href="...">' приведет к отображению буквальной строки вместо привязки. Вместо этого вы должны объявить теги в своем шаблоне и связать свойства key и name внутри этих тегов. Итак, вашего наблюдателя можно заменить следующим:

<template is="dom-repeat" items="{{items}}" as="item">
  <a href$="/item/[[item.key]]">[[item.name]]</a><br />
  [[item.date]]<br />
</template>

Итерация массива

Следующее примечание актуально только в том случае, если вы предпочитаете изменить данные перед их отображением ...

При итерации массива вы должны избегайте for..in, потому что он не гарантирует порядок итерации и потому, что он может перебирать перечисляемые свойства, которые могут вас не беспокоить. Вместо этого вы можете использовать _21 _ (при условии, что ES6 доступен вашему приложению):

for (let note of notes) {
  note.title += ' ...';
}

или Array.prototype.forEach():

notes.forEach(function(note) {
  note.title += ' ...';
});
person tony19    schedule 03.01.2017
comment
Большое спасибо, это очень информативно и очень ценно. В моем случае мне нужно было изменить данные перед отображением, и по какой-то причине я все еще не могу просмотреть данные из функции наблюдателя. Я добавил скриншот того, что console.log (data) показывает от наблюдателя в моем исходном посте. - person Hubert; 04.01.2017

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

<template is="dom-repeat" items="{{items}}" as="item">
  <child-el date="{{_computeDate(item.date)}}"></child-el><br />
  <child-el attr1="{{_someOtherConversion(item.prop1)}}"></child-el><br />
  <child-el attr2="{{_iPromiseAnyConversionCanBeDoneLikeThis(item.prop2)}}"></child-el><br />
</template>
<script>
  _computeDate: function(item) {
    //do date converstion
}
person Ryan Tyler    schedule 04.01.2017
comment
В основном это потому, что я передаю данные дочернему компоненту, который отображает их в красивой таблице. Поскольку дочерний компонент является универсальным, мне нужно заранее изменить некоторые данные. - person Hubert; 04.01.2017
comment
Измените его с помощью вычисленных привязок - person Ryan Tyler; 04.01.2017
comment
Я изменил свой ответ, чтобы ответить на ваш последний комментарий. - person Ryan Tyler; 05.01.2017