Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.0] Data-binding: Is there any way to do this imperatively? #1778

Closed
zerodevx opened this issue Jun 8, 2015 · 14 comments
Closed

[1.0] Data-binding: Is there any way to do this imperatively? #1778

zerodevx opened this issue Jun 8, 2015 · 14 comments

Comments

@zerodevx
Copy link

zerodevx commented Jun 8, 2015

Hello, considering the below snippet,

  var el = document.createElement("foo-element");
  el.setAttribute("foo", "[[foo]]");
  Polymer.dom(tpl.$.insertion_point).appendChild(el);

Full jsbin: (http://jsbin.com/hiloloqoju/1/edit)

In 0.5, I could simply imperatively import a Polymer element, then insert its markup into the DOM. Could I do something like that in 1.0?

Thanks so much,
J

@Pupix
Copy link

Pupix commented Jun 8, 2015

@zerodevx
Copy link
Author

zerodevx commented Jun 8, 2015

AFAIK, importHref simply tells Polymer to register/upgrade an element. After registering, how do you imperatively create and place a data-bound node into DOM?

My apologies, I might not have been clear earlier.

Declarative approach:

...
<link rel="import" href="my-foo.html">
...
<dom-module>
  <template>
    <!-- Look, I loaded <my-foo> and did a two-way bind declaratively -->
    <my-foo foo="{{bar}}"></my-foo>
  </template>
  <script>
    Polymer({
      is: "my-element",
      properties: { bar: String },
      ...
    });
  </script>
</template>

Imperatively, how do I do the above?

@Pupix
Copy link

Pupix commented Jun 8, 2015

Were you able to do

    el.setAttribute("foo", "[[foo]]");

and have it correctly execute the binding?

That seems rather strange.

Edit: Now that I think of it, it might have worked because they showed you the {{prop}} syntax in the DOM.

@zerodevx
Copy link
Author

zerodevx commented Jun 8, 2015

Nope, doesn't work, check out the jsbin: (http://jsbin.com/hiloloqoju/1/edit)

This used to work with 0.5 though.

@kevinpschaaf
Copy link
Member

No, we don't currently support this, outside of dom-bind, which is the only template implementation that late-binds instance children. You can document.createElement('template', 'dom-bind'), then you can dynamically append children with binding annotations to its content, and the bindings will only be evaluated once the dom-bind is attached to the document. See tests here that show this usage of it: https://github.com/Polymer/polymer/blob/master/test/unit/dom-bind.html#L95

Note that dom-bind does not currently allow binding to outer scope, so it has limited use in custom element templates (it's main use case is for binding between elements in the main document), and that's not likely to change short-term.

We are achieving a lot of performance optimization by baking the binding connections into the prototype at registration time for an element (rather than at instance time), and we haven't built up enough of the machinery to easily allow runtime addition/removal of bindings.

@zerodevx
Copy link
Author

zerodevx commented Jun 9, 2015

@kevinpschaaf

Thanks for the detailed explanation. I suppose I could kind of emulate the data-binding behaviour by:

  1. on parent element, importHref, then document.createElement the child element and append into DOM.
  2. on parent element, define an observer on change and pass in updates to child element.
  3. on child element, fire events on change to notify parent element.

@lichenhao
Copy link

So, if this is no longer available in Polymer, why should I use Polymer with my APP?

@Jookus
Copy link

Jookus commented Feb 24, 2016

Is this still up to date? Or rather, is there no easy way to dynamically import and create a custom element with data-binding properties?
I try to create a webapp with iron-pages that loads it's page-elements dynamically and get stuck because of missing databindings... 😞

@kaste
Copy link
Contributor

kaste commented Mar 4, 2016

Can you take a look at #3456 (and its related PR #3460) and perhaps comment if that would fix your issue.

@aahoo
Copy link

aahoo commented Jun 5, 2016

Any updates or plans for updates on this? or any workarounds?

@AliMD
Copy link
Contributor

AliMD commented Aug 18, 2016

I have same issue and search too much but finally use write this code to solve my problem.
I don't like this hard-way but I cant do it automatically.
I hope its useful for people search and find this issue.

my-element with ability to load other-element with two way data binding!

<dom-module id="my-element">
  <template>
    <style>
      :host {
        display: block;
      }
    </style>


    <div id="container">
      <button on-tap="changeFoo">Change Foo</button>
      <p>my-element: {{foo}}</p>
      <!-- <other-element foo="{{foo}}"></other-element> -->
    </div>
  </template>

  <script>
    (function () {
      'use strict';

      Polymer({
        is: 'my-element',

        properties: {
          foo: {
            type: String,
            value: 'foo'
          }
        },

        observers: [
          'setVar("foo", foo)'
        ],

        ready: function () {
          this._log('ready');

          if(!this.comp) this.makeComp();
          this.$.container.appendChild(this.comp);
        },

        changeFoo: function (){
          this.foo = Math.floor(Math.random()*1000);
        },

        makeComp: function () {
          this.comp = document.createElement('other-element');
          //this.comp.setAttribute('foo', '{{foo}}'); // not work!
          this.comp.addEventListener('foo-changed', this.getVar('foo'));
        },

        setVar: function (varName, value) {
          if(!this.comp) this.makeComp();
          this.comp[varName] = value;
          // this.comp.set function not defined
        },

        getVar: function (varName) {
          var _this = this;
          return function (evt) {
            var newValue = evt.detail.value;
            if(_this[varName] != newValue) {
              _this[varName] = newValue;
            }
          };
        }


      });

    })();
  </script>
</dom-module>

Check Demo

You can create dynamic <template id="dom-bind"> with and write any html code but i don't recommend it becouse your codes its not clean anymore and two way binding is very complex if you want make it dynamic like previous demo.
Demo for dynamic template (not recommended for two way binding)

@yanlee26
Copy link

same here ,and how can i get the data

var el = document.createElement("foo-element");
  el.setAttribute("foo", "[[foo]]");
  Polymer.dom(tpl.$.insertion_point).appendChild(el);

@yanlee26
Copy link

@AliMD not event match the problem,I need functions like dom to create doms dymamiclly depending on parsing the json data

@surinder83singh
Copy link

surinder83singh commented May 12, 2018

use a template :) , but issue is for each parent location of dyanamic component we need separate "myElements" and template definition

<template is="dom-repeat" items="{{myElements}}" >
    <other-element data-index="[[index]]" foo="{{foo}}" on-remove-me="removeChild">
</template>

{

	properties:{
		myElements:{
			type:Array,
			value:[]
		},
		foo:{
			type: String,
			value: ""
		}

	},
	ready:function(e){
		setInterval(()=>{
			this.set("foo", Math.random());
		}, 5000)
	},
	addNewElement:function(){
		this.push("myElements", { })
	},
	removeChild:function(e){
		this.splice("myElements", e.target.dataIndex, 1)
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants