Search code examples
htmldartpolymerdart-polymer

Add polymer-dart element to div


I'm trying to build a component that can switch other components in and out, almost like pages, but with no change in URL.

I have a polymer element that contains a content div:

<link rel="import" href="../../packages/polymer/polymer.html">

<link rel="import" href="../../packages/paper_elements/paper_input.html">
<link rel="import" href="../../packages/paper_elements/paper_input.html">
<link rel="import" href="../../packages/paper_elements/paper_tabs.html">
<link rel="import" href="../../packages/paper_elements/paper_dialog.html">
<link rel="import" href="../../packages/paper_elements/paper_icon_button.html">
<link rel="import" href="../../packages/core_elements/core_toolbar.html">
<link rel="import" href="../../packages/core_elements/core_scaffold.html">
<link rel="import" href="../../packages/core_elements/core_header_panel.html">
<link rel="import" href="../../packages/core_elements/core_menu.html">
<link rel="import" href="../../packages/core_elements/core_item.html">
<link rel="import" href="../../packages/paper_elements/paper_input.html">
<link rel="import" href="../../packages/paper_elements/paper_button.html">

<polymer-element name="navigation-toolbar" class="dark-primary-color">
    <template>
        <style type="text/css">
            :host {
                display: block;
            }

        </style>

        <core-scaffold>

            <core-header-panel id="menu-panel" navigation flex>

                <core-toolbar id="navheader">
                    <span>Menu</span>
                </core-toolbar>
                <core-menu>
                    <core-item label="A" on-click="{{aClicked}}"></core-item>
                    <core-item label="B" on-click="{{bClicked}}"></core-item>
                    <core-item label="C" on-click="{{cClicked}}"></core-item>
                </core-menu>
            </core-header-panel>

            <span tool>{{title}}</span>
            <paper-tabs class="main-menu bottom fit" selected="0">
                <paper-tab on-click="{{aClicked}}">A</paper-tab>
                <paper-tab on-click="{{bClicked}}">B</paper-tab>
                <paper-tab on-click="{{cClicked}}">C</paper-tab>
            </paper-tabs>

            <div class="content" forceNarrow>
               <p>Lorem ipsum ...</p>
            </div>
        </core-scaffold>
    </template>
    <script type="application/dart" src="navigation-toolbar.dart"></script>
</polymer-element>

I have an eventbus that fires events and receives events, it is used all over the application to allow me to decouple components.

part of util;

class EB {

  static EventBus _eventBus = new EventBus();

  static fire(event){
    _eventBus.fire(event);
  }

  static Stream on([Type eventType]) {
    return _eventBus.on(eventType);
  }

}

PageEvent which is being used to fire / listen for page events is just a PODO:

part of event;

class PageEvent {

  String page;
  String title;
  PolymerElement element;


  PageEvent.create(String page, String title, PolymerElement element){
    this.page = page;
    this.title = title;
    this.element = element;
  }


}

Inside the event library the relevant imports is being done for PageEvent:

library event;

import 'package:polymer/polymer.dart';

part 'login-event.dart';
part 'logout-event.dart';
part 'page-event.dart';
...

This event bus is then used in my core-scaffold component:

import 'package:polymer/polymer.dart';
import 'util/util.dart';
import 'event/event.dart';
import 'page/page.dart';
import 'dart:html';

@CustomTag('navigation-toolbar')
class NavigationToolbar extends PolymerElement {

  @observable String page = "home";
  @observable String title = "Home";

  NavigationToolbar.created() : super.created() {

    EB.on(PageEvent).listen((PageEvent e) {
      this.page = e.page;
      this.title = e.title;
      setPage(e.element);
    });

An event is fired upon clicking on one of the paper-tabs:

 // part of navigation-toolbar
 aClicked(event, detail, target) {
    EB.fire(new PageEvent.create("a", "A", new APage()));
  }

setPage is where the final magic is supposed to happen, but is not, both div and e is being printed out which tells me it is getting to the method and both e and div are not null:

 // part of navigation-toolbar
 setPage(PolymerElement e) {

    DivElement div = shadowRoot.querySelector("core-scaffold").querySelector(".content");
    Node node = div.lastChild;
    while (node != null) {
      node.remove();
      node = div.lastChild;
    }

    print(div);
    print(e);

    div.children.add(e);

  }

Printing out div, I can see the word div in the console which means it's not null, printing out e, I can see a-page, b-page, c-page, etc, that's not null either.

The code to clear the div works, it removes all content. The part that doesn't work is the div.children.add(e);

APage looks like this:

<link rel="import" href="../../../packages/polymer/polymer.html">

<polymer-element name="home-page" class="dark-primary-color">
    <template>
        <div>
            A Page
        </div>
    </template>
    <script type="application/dart" src="a-page.dart"></script>
</polymer-element>

and a-page.dart:

part of page;

@CustomTag('a-page')
class APage extends PolymerElement {

  APage.created() : super.created();

  factory APage() => new Element.tag('a-page');

}

Adding an import for a-page.html in navigation-toolbar.html

<link rel="import" href="page/a-page.html">

Gives me the following exception:

'package:falm/page/a-page.dart': error: line 1 pos 6: url expected
part of page;
     ^: package:falm/page/a-page.dart 

div.children.add(e); doesn't work, what am I missing here?


Solution

  • After messing around a bit, I found a way that works - it seems polymer elements doesn't play nice when included in a library.

    This was what a-page.dart looked like:

    part of page;
    
    @CustomTag('a-page')
    class APage extends PolymerElement {
    
      APage.created() : super.created();
    
      factory APage() => new Element.tag('a-page');
    
    }
    

    and the page.dart library:

    library page;
    
    import 'package:polymer/polymer.dart';
    import 'dart:html';
    
    part 'a-page.dart';
    part 'b-page.dart';
    part 'c-page.dart';
    

    After removing the page library and putting all the dependencies straight inside a-page.dart:

    import 'package:polymer/polymer.dart';
    import 'dart:html';
    
    @CustomTag('a-page')
    class APage extends PolymerElement {
    
      APage.created() : super.created();
    
      factory APage() => new Element.tag('a-page');
    
    }
    

    inside my navigation-toolbar.dart, instead of importing page/page.dart, I need to import each page individually:

    import 'page/a-page.dart';
    import 'page/b-page.dart';
    import 'page/c-page.dart';
    
    ...
    
      setPage(PolymerElement e) {
    
        DivElement div = shadowRoot.querySelector("core-scaffold .content")
        ..children.clear()
        ..append(e);
    
      }
    

    and on navigation-toolbar.html, I need to import each html component as well for it to work:

    <link rel="import" href="page/a-page.html">
    <link rel="import" href="page/b-page.html">
    <link rel="import" href="page/c-page.html">
    

    Is it even possible to include polymer elements in a library?