Will Angular 2.0 understand Polymers shadow DOM?

In preparation for angular 2.0 I am using polymer. Does anyone know if the current polymer implementation is ready so that Angular 2.0 will be able to receive updates from polymer components/models. Currently only polymer can listen to angular model updates.

I would like my current UI to be ready for angular 2.0 ideally without having to modify the polymer code too much.

How to set the property of a Polymer component from an Angular 2 object?

I’m getting started with Angular 2 and Polymer, I got them working separately as expected, but I have trouble mixing them up. I’m trying to set the icon property of an iron-icon from the value of an Angular object. Here is my code, modified from the one in the tutorial:

TS file:

import {Component, View, bootstrap, CORE_DIRECTIVES} from 'angular2/angular2';
@Component({ selector: 'hero-manager' })
@View({
  directives: [CORE_DIRECTIVES],
  templateUrl: "hero/hero.tpl.html",
})
class HeroComponent {
  public hero = {"id": 1, "name": "foo", "icon": "polymer"};
}
class Hero {
  id: number;
  name: string;
  icon: string;
}

bootstrap(HeroComponent);

hero.tpl.html

<link rel="import" href="../bower_components/iron-icons/iron-icons.html">

<div><iron-icon icon="polymer"></iron-icon>{{hero.icon}}</div>
<div><iron-icon [icon]="'polymer'"></iron-icon>{{hero.icon}}</div>
<div><iron-icon icon="{{hero.icon}}"></iron-icon>{{hero.icon}}</div>
<div><iron-icon [icon]="hero.icon"></iron-icon>{{hero.icon}}</div>

I tried different ways to set the polymer value for the icon property. Only the first of the 4 lines work and displays the icon. In the dev tools there is no icon property for the 3 others. Meanwhile, {{hero.icon}} in the div is properly expanded to polymer.

What should I do to be able to dynamically set the icon property?

Edit: I reproduced the issue in this plunker, derived from @Eric Martinez’s comment.

The iron-icons import is in the template instead of being in the main html

Edit 2, after @Eric Martinez comment that says that I should be using [attr.icon]:

New questions:

  • According to iron-icon’s sources, icon is a property, defined in the property object. Where is the attr notation coming from? Angular and Polymer have to completely different understandings of what properties should be?

  • Why did it work when the import is done in index.html?

Polymer Dart as a SPA framework

I know that polymer is primarily used to create reusable elements, and angular is supposed to be used to create web apps (at least from a “high level” perspective), but I wonder, since you can wrap your own “Screens” as polymer elements, which actually could serve as controllers too, and switch the active page with the iron-pages element (see SPA demo), and you can also use more-routing well… instead of “routing by code”, it supports one/two way binding and events, I’ve actually done some small SPA app like that myself, and so far so good actually! moving on-

Assuming I don’t care about having some built-in REST wrapper such as the one provided by Angular (Easy to roll up my own if I use Dart), then in Dart’s case:

  1. Could polymer actually be used to create full apps?
  2. Would it have any implications in performance if my whole app is in polymer? by that I mean, every screen is really an element, and so on.
  3. Development speed, maintainability, and experience? (considering the fact that I use Dart which helps a lot in these areas)
  4. Overall, is it a good idea? I’d like to know your opinions.
  5. Any companies/indie devs have done this before? not necessarily with Dart, but with TypeScript/JS as well, although I’m 100% set on Dart.

Bind angular 2 model to polymer dropdown

I decided to take some time this weekend to look at Angular 2 and Polymer. I’m really interested in angular 2 and would really like to start building something with it. One downside with starting with Angular 2 now is that there is no good component library yet. However, since Angular 2 claims that it should work so good together with Web Components I thought of giving Polymer a try. I have succeeded to bind data to simple components like an input field. What I’m stuck at for the moment is how to bind a model to the selected object of a paper-dropdown-menu. Since I’m very new into both I don’t really know how to do it but this is what I have tried so far. Has anyone accomplished to bind an angular 2 model to a polymer dropdown?

<paper-dropdown-menu  >
   <paper-menu class="dropdown-content" valueattr="id" [(ng-model)]="model">
       <paper-item *ng-for="#m of options" id="{{m.id}}" (click)="onClick()">{{m.name}}</paper-item>
   </paper-menu>
</paper-dropdown-menu>

EDIT: I have now created a ValueAccessor which seems to work acceptable with one exception. I try to get the dropdown to have a pre-selected value by setting the selected attribute in the writeValue method. At first this seemed to work but after I made this change I can no longer change the selected value. It works if I hardcode the value in the template so it seems to have something to do with angular together with polymer. I tried to follow the stacktrace and compare the difference between the two are. When I hardcode the value a setter method for selected is executed which trigger an item-select event. When I follow the same trace when I set the property in the valueAccessor there the setter method is no longer executed. Seems to be a problem with the interaction between angular 2 and polymer.

import {Directive, ControlValueAccessor, ElementRef, Renderer, NG_VALUE_ACCESSOR, Provider, forwardRef} from "angular2/angular2"
import {isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
import {setProperty} from "angular2/src/common/forms/directives/shared"

const PAPER_DROPDOWN_VALUE_ACCESSOR = CONST_EXPR(new Provider(
    NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => PaperDrowpdownMenuAccessor), multi: true}));

@Directive({
  selector: 'paper-menu[ng-model]',
  bindings: [PAPER_DROPDOWN_VALUE_ACCESSOR]
})
export class PaperDrowpdownMenuAccessor implements ControlValueAccessor {

  onChange = (_) => {};
  onTouched = () => {};

  constructor(private _renderer: Renderer, private _elementRef: ElementRef) {
    var self = this;
    this._elementRef.nativeElement.addEventListener('iron-select', function(e, v, s){
      console.log(e.target.selected);
      self.onChange(e.target.selected);
    });
  }

  writeValue(value: any): void {
    if(value){
      if(this._elementRef.nativeElement.select) {
        this._elementRef.nativeElement.select(value);
      }
      else {
        //this._elementRef.nativeElement.attributes["selected"]
        setProperty(this._renderer, this._elementRef, 'selected', value);
      }
    }       
  }

  registerOnChange(fn: () => any): void { 
    this.onChange = fn; 
  }
  registerOnTouched(fn: () => any): void { this.onTouched = fn; }
}

Polymer elements within angular 2 component

I have a set of custom polymer elements, that I would like to use within an angular 2 application.

It seems like there’s a problem concerning the content tag of the polymer element. The content of the element gets rendered at the wrong place within the polymer element, if the element is located within an angular 2 component.

Example:

The template of my polymer element “my-button” looks like this:

<template>

  <button>
    <content></content>
  </button>

</template>

Use outside angular

When I use this element outside of my angular 2 component, I get the result that I expected:

Use:

<my-button>Foo</my-button>

Result:

<my-button>
  <button>
    Foo
  </button>
<my-button>

Use within angular 2 component

When used within an angular 2 component, the content always gets rendered at the end of the elements template. Just like the content tag didn’t exist.

Use:

<my-button>Foo</my-button>

Result:

<my-button>
  <button>

  </button>
  "Foo"
<my-button>

Question

The problem might be, that polymer and angular 2 both use the content tag for transclution. So maybe things get a little messy when using both together.

I would love to use all of my polymer elements inside angular 2. So any ideas on how to fix this would be very much appreciated.

Polymer paper element attributes and Angular

I am using Angular and Google Polymer paper elements. Works fine, but I have problems with attributes. While this does work:

<paper-card>{{someVarFromComponent}}</paper-card>

This does NOT:

<paper-card heading="{{someVarFromComponent}}"></paper-card>

someVarFromComponent is a variable of my component. It seems providing variables to templates does not work in the parameters. Or it does not work in parameters for polymer components?

I need to change the content of the heading attribute in <paper-card> when my component variable someVarFromComponent changes.

Is there a solution or workaround for this problem?

Use polymer paper element on angular 2 project

I’m actually trying to use Angular 2 with angular cli and I’m having a problem with polymer paper elements components.

Actually, I link this inside of my <head> tag:

<link rel="import" href="../bower_components/paper-header-panel/paper-header-panel.html"/>

But the component doesn’t load when I try this:

<paper-header-panel class="blue">
    <div class="paper-header">standard</div>
    <div class="content"></div>
  </paper-header-panel>

Now, it seems that I can’t find the package, the browser tries to request :

http://127.0.0.1:4200/bower_components/paper-header-panel/paper-header-panel.html

But nothing is found.

How can I make it work?

Generating Polymer element's content with Angular2

I’m trying to use Polymer element <paper-tabs> in combination with Angular2 like:

<paper-tabs>
    <paper-tab *ngFor="#tab of tabs">{{ tab }}</paper-tab>
</paper-tabs>

From Angular’s perspective this is correct but it completely breaks the Polymer element.

It’s probably because I’m modifying elements inner content that is placed inside paper-tabs using <content> tag.

See plnkr.co demo
(note: it requires disabled browser CORS because it links paper-tabs.html directly from elements.polymer-project.org).

In the demo there’re are two <paper-tabs>. First one is controller by Angular2. If you press “add tab” button several times it adds them to the menu until you press any of the tabs. Then they disappear and you can’t add any more tabs. The second menu is ‘vanilla’ Polymer which is outside Angular and works fine.

I’ve used Polymer elements with Angular2 before. For example <google-chart> works well because I had to pass variable from Angular to the element. This was easy since I could set element’s attribute directly.

<!-- somewhere in a component's template -->
<google-chart #chart></google-chart>

Then somewhere in component’s implementation:

var options = {
    'legend': {
        'position': 'none'
    },
    'chartArea': {
        'width': '80%',
        'height': '75%',
        'left': '15%',
        'top': '5%'
    }
};

// grab the <google-chart> element
var elm = this._viewManager.getNamedElementInComponentView(this._elementRef, 'chart').nativeElement;
elm.options = this.options;
elm.type = 'line';

The same attitude works also for binding events which is nicely explained in this video “Componentize your app with Polymer Elements” from AngularU by Rob Dodson.

However, using <paper-tabs> is different and I have no idea how to use it. The same problem’s going to be with any Polymer element that relies on its inner HTML content that you want to modify by Angular2.

Using Angular 2 two-way data binding with Polymer

I’m trying to combine Polymer elements with Angular 2 and I struggle with the two-way data binding aspect.

As an example I use paper-tabs and display the tab number that is currently in use. Whenever I change a tab, I want that change to happen in a tabNr field in the AppComponent as well. Whenever I click on the tab number that is being displayed, I want the number to change and change the tab accordingly. My initial approach was this:

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `
                <paper-toolbar>
                    <paper-tabs [(selected)]="tabNr">
                        <paper-tab>Tab 1</paper-tab>
                        <paper-tab>Tab 2</paper-tab>
                        <paper-tab>Tab 3</paper-tab>
                    </paper-tabs>
                </paper-toolbar>
                <paper-toolbar>
                    <div (click)="traverse()">Tab {{tabNr + 1}}</div>
                </paper-toolbar>
                `
})
export class AppComponent {
    tabNr = 0;

    traverse() {
        this.tabNr = (this.tabNr + 1) % 3;
    }

}

However, this does not work. I can’t change the tabs. I can click the Tab number being displayed to change that, but that is also not reflected in the actual tabs. In the following I’ll focus on that line in the code to discuss all other possibilities I tried out:

<paper-tabs [(selected)]="tabNr">

I was expecting that one way data-binding (paper-tabs going to the AppComponent) would work like this

<paper-tabs (selected)="tabNr">

but that doesn’t work. To actually get the changes to register, I need to use the event from Polymer like this:

<paper-tabs selected="tabNr" (selected-changed)="tabNr=$event.detail.value">

That defeats the purpose of using Angular 2 for the bindings. It seems to me that the problem here is, that polymer is firing a different event for the change than whatever Angular 2 is expecting.

In order to get the click-changes to register with the tabs I have to do this:

<paper-tabs [attr.selected]="tabNr">

However, I cannot combine both of those result into this

<paper-tabs [attr.selected]="tabNr" (selected-changed)="tabNr=$event.detail.value">

because I get the following exception whenever I change a tab:

EXCEPTION: Expression ‘tabNr in AppComponent@2:17’ has changed after
it was checked. Previous value: ‘1’. Current value: ‘1’ in [tabNr in
AppComponent@2:17]

I assume there is probably some sort of circular event firing going on. I can solve this by using a method for the (selected-changed) event that only changes it if the number of the event is actually a different number, but that whole approach seems cumbersome and I derived quite a bit from simply using [()] to bind the data.

So my question is:
Is there a better, cleaner way to do this?