Phil
Phil

Reputation: 2252

Binding to a Custom Element in a Template Part in Aurelia

I've created a plunkr to illustrate the problem I'm having.

I'm in the middle of creating a dashboard which at the moment contains four different items. Each of these items I'm creating as Custom Elements then wrapping them in a Custom Element called Widget to give them a frame, title and styling. Here's what that snippet looks like:

<widget title="A Widget" icon="fa-question">
  <template replace-part="item-template">
    <child-element text.bind="$parent.$parent.someText"></child-element>
  </template>
</widget>

For reference the widget view looks like this:

<template>
  <require from="./widget.css!"></require>
  <div class="widget">
    <div class="widget-header">
      <i class="fa ${icon}"></i>
      <h3>${title}</h3>
    </div>
    <div class="widget-content">
      <template replaceable part="item-template"></template>
    </div>
  </div>
</template>

and the view model is:

import {bindable} from "aurelia-framework";
export class WidgetCustomElement {
  @bindable title;
  @bindable icon;
  @bindable show; // This is something I want the child element
                  // to be able to bind to and control but haven't
                  // got there yet!!
}

But notice I'm trying to bind data from the ViewModel into the child-element where the child-element looks like this:

import {bindable} from "aurelia-framework";
export class ChildElementCustomElement {
  @bindable text;
}

and the view:

<template>
  <p>The widget passed us : ${text}</p>
</template>

The problem is no matter what expression I use (and here I'm currently trying $parent.$parent.someText) I can't get the binding to work.

Should this work? I've also tried defining the variable someText in the main ViewModel as `@bindable someText' but that throws the following exception:

Unhandled promise rejection TypeError: Cannot read property 'some-text' of null
    at BindableProperty.initialize (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/github/aurelia/[email protected]/aurelia-templating.js:2448:33)
    at new BehaviorInstance (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/github/aurelia/[email protected]/aurelia-templating.js:2199:23)
    at HtmlBehaviorResource.create (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/github/aurelia/[email protected]/aurelia-templating.js:2821:30)
    at https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/github/aurelia/[email protected]/aurelia-templating.js:3385:27
    at f (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/npm/[email protected]/client/shim.min.js:1415:56)
    at https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/npm/[email protected]/client/shim.min.js:1423:13
    at b.exports (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/npm/[email protected]/client/shim.min.js:453:24)
    at b.(anonymous function) (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/npm/[email protected]/client/shim.min.js:1625:11)
    at Number.f (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/npm/[email protected]/client/shim.min.js:1596:24)
    at q (https://cdn.rawgit.com/jdanyow/aurelia-plunker/v0.4.0/jspm_packages/npm/[email protected]/client/shim.min.js:1600:11)

Upvotes: 4

Views: 3870

Answers (2)

Phil
Phil

Reputation: 2252

I have since stumbled across something in the Aurelia document detailing Template Parts. In example.js a bind() method is defined which assigns the bindingContext to a local member this.$parent.

This means all I have to do is defined the following in the view model for my widget:

bind(bindingContext) {
   this.$parent = bindingContext;
}

Then the child-element is bound with the following:

<child-element text.bind="$parent.someText"></child-element>

I've forked my original plunkr to demonstrate it working.

Given repeat-for provides it's own $parent I had mistakenly believed there was one automatically defined here!!

Upvotes: 1

Sayan Pal
Sayan Pal

Reputation: 4956

I am not sure whether you are looking for this or not, however, introducing a @bindable text property in WidgetCustomElement makes this a whole lot easier. I worked on your plunk and introduced a @bindable wtext; in WidgetCustomElement, used this property to bind someText in app view like below:

<widget title="A Widget" icon="fa-question" wtext.bind="someText">
   <template replace-part="item-template">
        <child-element text.bind="wtext"></child-element>
        <!--<child-element text.bind="$parent.$parent.someText"></child-element>-->
   </template>
</widget>

And this works. However as I said I am not sure whether this approach works for you or not. What I have assumed is your widget will mostly contain one single child element and if this assumption is correct then this should work, however in case one-to-many mapping (many child element in single widget), something else is needed.

Hope this helps.

EDIT: I forked your plunk to make the changes and here is the link to that.

Upvotes: 1

Related Questions