Get name of attribute bound to

Is it possible to get the name of an attribute that is bound to?

Here is a jsbin as an example.

What I am aiming at is to return the errors for the bound attribute to display under the bound control.

So something like this:

Since, currently, an errors() function returns all the errors for a can.Map I would like to return only those for a given attribute using some convention mechanism.

Any ideas?

I assume you are using the old validations plugin. I haven’t used the new one.

I find your title confusing, but if I am correct in thinking that you simply want to display some errors, there are a few ways to do this. The simplest is probably with a stache helper.

can.stache.registerSimpleHelper('showErrors', function(map, fieldName) {
  var errors = map.errors(fieldName);
  if (errors) {
    return errors[fieldName];
  }
});

Usage:

<input {($value)}="map.username"></input>
{{showErrors map 'username'}}

Notes:

  • Make sure your map is accessible where you want to show the errors because it needs to be passed to the helper.
  • If you want to return html in the helper such as <span class="error">{{error}}</span> then use triple braces when using the helper so the output is not escaped

You will inevitably also wonder about blocking a submission if there are errors. Simply checking map.errors().length in your submit method may be sufficient, but if you have a complex model or view, it may be appropriate to make components to manage checking/showing errors which I am doing in my current project.

…

Analyzing this a bit more, if you want your <composite-textfield> component to be able to show errors on its own, I don’t think that’s possible if you only pass the bound field. I would pass the map and the name of the field to it like this:

<!-- app -->
<composite-textfield text="even lower" {(value)}="username"
    {validate-map}="." validate-field="username"></composite-textfield>

<!-- composite-textfield -->
<input {($value)}="value"></input>
{{showErrors validateMap validateField}}

However, I believe one of the goals of the new validations plugin is that a compute itself could carry validations with it so something like that might be possible in the future.

1 Like

Well, actually I am trying to get the name of the attribute that the value is bound to so that I do not need to pass it in.

I am no Ember fan but what one can do with Ember is pass only the path and then do the binding using code. One can also retrieve the value binding from code.

If not possible then so be it. Slightly more work though for users of the component.

I don’t think it’s documented, but you can inspect a compute to get its original context (the map), but the child component’s value compute is a separate one from the parent scope that is simply bound, so there is no handle to the parent compute because we can’t access the closured one in the change handler.

In order to do this, you would have to past string “username” instead of using the standard binding syntax. You would then have to get a handle to the parent scope and create the compute yourself, which would then allow you to get a handle the to map from which it was derived with something like:

var valueCompute = scope.compute(fieldName);
var map = valueCompute.computeInstance.observedInfo.context;
var errors = map.errors(fieldName);

I’m just not sure of an easy way to get the parent scope. It is straight forward in a custom attribute because it’s passed in, but with a component you really only get the element and I don’t know how to get the scope from an element.

…

Another possible option would be to pass the compute directly to the component. This should be possible with {(value)}="~username" for instance but it seems to just be passing the value of the compute which is probably a bug.