5

I have a component that accepts an array of values and array of the same length with a validation error string for each value. I'd like to display a list of form fields with inputs for each value and error pair. I've tried creating a computed property like this:

var myComponent = Ember.Component.extend({
  //values: <provided array of input values>
  //errors: <provided array of error strings>
  valuesAndErrors: function() {
    var combined = [];
    for (var i = 0; i < values.length; i++) {
      combined.pushObject({
        value: this.get('values')[i],
        error: this.get('errors')[i]
      });
    }
    return combined;
  }.property('values.@each', 'errors.@each')
});

But unfortunately the changes made to values in valuesAndErrors (e.g. via {{input value=valuesAndErrors.value}}) are not pushed back to the source values array. What is the correct way to iterate over the values and errors arrays simultaneously without breaking bindings like this?

I'm currently using Ember 1.9.

pmdarrow
  • 734
  • 5
  • 14
  • 1
    I'm not sure if you're talking about the actual values from `values` and `errors` or if you're talking about the computed property not updating. If you're talking about the first, strings are passed by value, so you'd need to wrap them in an object in order to share them among two arrays. If you're talking about the second, you're property might want to watch `values.[]` and `errors.[]` in order to see values and errors change. – Kingpin2k Jan 17 '15 at 01:15
  • I'm not having issues with the computed property not updating - I'm having issues with the actual changes to values in `valuesAndErrors` (via `{{input value=valuesAndErrors.value}}`) not being pushed back to the source `values` array. Does this make more sense? – pmdarrow Jan 17 '15 at 05:12
  • Can you modify the values and errors array (I only say this, cause that's the only way ;) ) – Kingpin2k Jan 17 '15 at 19:43
  • I suppose I could modify the `values` array but how would I keep those changes in-sync with the original `errors` array? – pmdarrow Jan 19 '15 at 13:38

1 Answers1

1

Instead of passing in a separate array for values and errors, why not have a computed property in the controller that combines the two and then pass that into the component?

So, your controller might look something like this:

App.ApplicationController = Ember.Controller.extend({
  values: function(){
    return ["one", "two", "three"];
  }.property(),

  errors: function(){
    return ["oneError", "twoError", "threeError"];
  }.property(),

  valuesAndErrors: function() {
    var combined = [];

    var values = this.get('values');
    var errors = this.get('errors');

    values.forEach(function(value, index){
      combined.pushObject({
        value: value,
        error: errors[index]
      });      
    });

    return combined;
  }.property('values.@each', 'errors.@each')
});

And your component template (you don't even need any component JS for this to work):

<script type="text/x-handlebars" id='components/value-error'>
  <h2>Inside of Component</h2>
    {{#each item in valuesAndErrors }}
      {{ input value=item.value }} - {{ input value=item.error }}<p/>
    {{/each}}
</script>

Working example here

UPDATE

enter image description here

Kalman
  • 8,001
  • 1
  • 27
  • 45
  • Unfortunately this breaks the two way bindings. If I make a change in any the `{{input value=item.value}}` input, it doesn't make it back to the "original" `values` array. – pmdarrow Feb 04 '15 at 21:39
  • Did you try editing the values in the Output tab in jsbin? Above is what I see when I edit – Kalman Feb 04 '15 at 21:47
  • Yes—the bindings are maintained within the combined `valuesAndErrors` array but the bindings back to the original `values` and `errors` arrays are broken. I've updated your JSBin to demonstrate the issue: http://emberjs.jsbin.com/pozoxaretu/1/edit?html,js,output. – pmdarrow Feb 06 '15 at 15:01
  • @pmdarrow - you crack me up :) `values` will ALWAYS 100% of time will return exactly the same thing. You know why? because it returns `return ["one", "two", "three"];` It's not a computed property. The bottom line - I think I fulfilled your intention, although sure the original non-changing `values` property will neva change :) – Kalman Feb 06 '15 at 15:40
  • Sorry, I didn't really read your code thoroughly. Assume `values` is an `Ember.A` instance and not a property that returns and array. My intention is to have `values` and `errors` bound to `valuesAndErrors` so I don't think this achieves that. – pmdarrow Feb 06 '15 at 19:37