Споделено състояние на поведение в персонализирани елементи

Имам тези два персонализирани полимерни елемента (Polymer 1.0.3):

  1. Показва текст за превод.
  2. Показва бутон за задействане на зареждането на превода.

Имам и Поведение, което съдържа преводите (json обект) и съдържа всички функции, които правят превода възможен.

Ето какво очаквам да се случи:

  1. Щракнете върху бутона в Елемент 2
  2. Преводите се зареждат в Behavior
  3. Изборът на език се задава в поведението
  4. Текстът в Елемент 1 се актуализира с преведен еквивалент

Стъпки 1 - 3 се случват, но 4 не. Текстът никога не се актуализира. Мога да го накарам да работи, ако Елементи 1 и 2 са комбинирани като един и същ елемент, но не и ако са отделни (всеки трябва да са отделни).

Ако се чудите за свойството "ритник", това е нещо, което научих от Polymer 0.5. Нещата заработиха, когато двата елемента бяха комбинирани, така че мисля, че ще е необходимо, когато елементите са отделни.

Някаква идея как мога да направя това? Отворен съм към алтернативни парадигми.

Код

Това е приблизително как е изложен моят код. Направих също плънкер с тестов случай от една страница.

index.html

<!doctype html>
<html>

<head>
  <script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
  <link rel="import" href="/bgbehavior.html">
  <link rel="import" href="/bgelement1.html">
  <link rel="import" href="/bgelement2.html">
</head>

<body>
  <my-element></my-element>
  <another-element></another-element>
</body>

</html>

Елемент 1

<dom-module id="my-element">
  <template>
    <p>{{localize(label, kick)}}</p>
  </template>
</dom-module>

<script>
  Polymer({
    is: 'my-element',
    behaviors: [
      behavior
    ],
    properties: {
      label: {
        type: String,
        value: 'original'
      }
    }
  });
</script>

Елемент 2

<dom-module id="another-element">
  <template>
    <button on-click="buttonClicked">load</button>
  </template>
</dom-module>
<script>
  Polymer({
    is: 'another-element',
    behaviors: [
      behavior
    ],
    buttonClicked: function() {
      this.registerTranslation('en', {
        original: 'changed'
      })
      this.selectLanguage('en');
    }
  });
</script>

Поведение

<script>
  var behavior = {
    properties: {
      kick: {
        type: Number,
        value: 0
      },
      language: {
        type: String,
        value: 'fun'
      },
      translations: {
        type: Object,
        value: function() {
          return {};
        }
      }
    },
    localize: function(key, i) {
      if (this.translations[this.language] && this.translations[this.language][key]) {
        return this.translations[this.language][key];
      }
      return key;
    },
    registerTranslation: function(translationKey, translationSet) {
      this.translations[translationKey] = translationSet;
    },
    selectLanguage: function(newLanguage) {
      this.language = newLanguage;
      this.set('kick', this.kick + 1);
    }
  };
</script>

person losttime    schedule 10.06.2015    source източник


Отговори (1)


Първо, въпреки че идеята е behavior да бъде канал за споделени данни между инстанции, както е написано, всяка инстанция ще има собствено копие на обекта translations и свойството kick.

Второ, дори ако тези данни са били приватизирани, за да могат да бъдат споделени, kick свързването, направено чрез localize(label, kick), е в различен обхват от израза, който модифицира kick (т.е. this.set('kick', this.kick + 1); [{sic} това може да бъде просто this.kick++;]).

За да уведомите N екземпляра за промяна в споделените данни, трябва да следите тези екземпляри. Добър начин да направите това е като прикачите слушатели на събития. Друг начин е просто да поддържате списък.

Ето примерна реализация на вашия дизайн:

    <script>
      (function() {
        var instances = [];
        var translationDb = {};
        var language = '';

        window.behavior = {
          properties: {
            l10n: {
              value: 0
            }  
          },
          attached: function() {
            instances.push(this);
          },
          detached: function() {
            this.arrayDelete(instances, this);
          },
          _broadcast: function() {
            instances.forEach(function(i) {
              i.l10n++;
            });
          },
          localize: function(key, i) {
            if (translationDb[language] && translationDb[language][key]) {
              return translationDb[language][key];
            }
            return key;
          },
          registerTranslation: function(translationKey, translationSet) {
            translationDb[translationKey] = translationSet;
          },
          selectLanguage: function(newLanguage) {
            language = newLanguage;
            this._broadcast();
          }
        };
      })();
  </script>

  <dom-module id="my-element">
    <template>
      <p>{{localize(label, l10n)}}</p>
    </template>
    <script>
      Polymer({
        behaviors: [
          behavior
        ],
        properties: {
          label: {
            type: String,
            value: 'original'
          }
        }
      });
    </script>
  </dom-module>

  <dom-module id="another-element">
    <template>
      <button on-tap="buttonClicked">load</button>
    </template>
    <script>
      Polymer({
        behaviors: [
          behavior
        ],
        buttonClicked: function() {
          this.registerTranslation('en', {
            original: 'changed'
          });
          this.selectLanguage('en');
        }
      });
    </script>
  </dom-module>
person Scott Miles    schedule 10.06.2015