How can I access the attribute from the template?

152 Views Asked by At

In this example i'm expecting it to say "hello world" but the world isn't picked up from the saying attribute.

(function () {
    'use strict';

    $(function () {
        // Set up a route that maps to the `filter` attribute
        can.route(':filter');

        // Render #app-template
        $('#app').html(can.view('appTemplate', {}));

        // Start the router
        can.route.ready();
    });

    can.Component.extend({
        tag: "say",
        scope: {
            saying: function(){
                return this.attr('saying')
            },
            greeting: 'salutations'
        },
        template: can.view("sayTemplate")
    });

})();

Templates:

<div id="app"></div>

<script id="appTemplate" type="text/mustache">
  <b>Hello</b>
  <say saying="world"></say>
</script>

<script id="sayTemplate" type="text/mustache">
    <b>{{saying}}.</b> <i>{{greeting}}</i>
</script>
1

There are 1 best solutions below

1
On BEST ANSWER

You need to tell the component that you want to access the attributes plain value like this:

can.Component.extend({
  tag: "app-say",
  scope: {
    saying: '@',
    greeting: 'salutations'
  },
  template: can.view("sayTemplate")
});

See this Fiddle. What you eventually might want to do use an observable attribute from your application state instead of the plain string value. This might look like:

var appState = new can.Map({
    name: 'World'
});

$(function () {
    // Set up a route that maps to the `filter` attribute
    can.route(':filter');

    // Render #app-template
    $('#app').html(can.view('appTemplate', appState));

    // Start the router
    can.route.ready();
});

can.Component.extend({
    tag: "app-say",
    scope: {
        greeting: 'salutations'
    },
    template: can.view("sayTemplate")
});

And a template like:

<div id="app"></div>

<script id="appTemplate" type="text/mustache">
  <b>Hello</b>
  <app-say saying="{name}"></app-say>
  <div><input type="text" can-value="name"></div>
</script>

<script id="sayTemplate" type="text/mustache">
    <b>{{saying}}.</b> <i>{{greeting}}</i>
</script>

This also creates a cross-bound input field that will update the name everywhere whenever you update the text field. Fiddle is here.