Ractive computed property

2019-09-19 02:47发布

问题:

I've got a simple test application using firebase with the following template and model in ractive. I want to access the price value in the computed newprice to format it to look like currency with 2 decimal places. I can't figure out though how to get at the .price value which displays fine in the output but nothing I've tried seems to be able to see .price inside the computed. The call to newprice works fine as I can just return text and see it in the output. The reason it am using .price is that the returned data from firebase has each make,model,price wrapped in a unique autogenerated id so I see a top level object with each entry id and the data within as an object with make,model,price.

<script id='template' type='text/ractive'>
{{#each listdata:i}}
    <p>{{ .make }} {{ .model }}{{.price}} ${{ newprice() }}!</p>
{{/each}}
</script>
<script>
    var ractive = new Ractive({
      // The `el` option can be a node, an ID, or a CSS selector.
      el: 'container',

      // We could pass in a string, but for the sake of convenience
      // we're passing the ID of the <script> tag above.
      template: '#template',
      computed: {
        newprice: function() {
          // CAN'T FIGURE OUT WHAT TO DO HERE TO SEE price
          return  ;
        }
      }
    });

</script>

Need some direction on how to get to .price value.

回答1:

Computed properties are referenced as properties, not functions. And, more importantly, are "absolute" keypaths so they won't work against a collection. To get this to work you have two options:

Use a data function

Instead of a computed property, use a data function:

<script id='template' type='text/ractive'>
{{#each listdata:i}}
    <p>{{ .make }} {{ .model }}{{.price}} ${{ newprice(.price) }}!</p>
{{/each}}
</script>
<script>
    var ractive = new Ractive({
      el: 'container',
      template: '#template',
      data: {
        newprice: function(price) {
          return price + 1;
        },
        // other data
      }
    });

</script>

You may find it more convientent to place the helper function "globally":

Ractive.defaults.data.newprice = function(price){...}

If you have an existing/favorite library, you can also use this technique and access methods inline in your template

<script src="path/to/accounting.js"></script>
Ractive.defaults.data.accounting = accounting

<p>{{ .make }} {{ .model }}{{.price}} ${{ accounting.formatMoney(.price) }}!</p>

Use a computed property, but at the component level

Use a component to render each item and then the computed property will be per item:

<script id='template' type='text/ractive'>
{{#each listdata:i}}
    <line/>
{{/each}}
</script>

<script id='line' type='text/ractive'>
    <p>{{ make }} {{ model }}{{price}} ${{ newprice }}!</p>
</script>

<script>
    Ractive.components.line = Ractive.extend({
      template: '#line',
      computed : {
        newprice: function(){
           return this.get('price')
        }
      }
    })
    var ractive = new Ractive({
      el: 'container',
      template: '#template',
    });

</script>


回答2:

Computed properties apply to the whole template - in other words there's no listdata[0].newprice and so on in the example above, only one newprice.

Instead, you need to create a function that Ractive can access from inside the template, and pass the old price into it:

<!-- language: lang-html -->

{{#each listdata:i}}
  <p>{{ .make }} {{ .model }}: {{.price}} -> ${{ newprice( .price ) }}!</p>
{{/each}}

<!-- language: lang-js -->

var ractive = new Ractive({
  el: 'main',
  template: '#template',
  data: {
    listdata: [
      { make: 'Toyota', model: 'Prius', price: 25000 },
      { make: 'Dodge', model: 'Challenger', price: 30000 },
      { make: 'Jeep', model: 'Grand Cherokee', price: 35000 },
      { make: 'Bugatti', model: 'Veyron', price: 2000000 }
    ],
    discount: 0.1,
    newprice: function ( oldprice ) {
      return oldprice * ( 1 - this.get( 'discount' ) );
    }
  }
});

Here's a JSFiddle to demonstrate: http://jsfiddle.net/rich_harris/nsnhwobg/