Assign all new attributes to specific element (Transparent Wrapper Components)


#1

Hello,

One of the brilliant features in Vue.js is ability of assign new attributes to specific element in template. known as Transparent Wrapper Components

for example I created a component

 <label aut-uuid ref="floatInputLabel">
    <input id="${id}" ref="floatInput" class="${class}" css="${style}" type="${type}" placeholder="${placeholder}" />
    <span>
      <slot></slot>
    </span>
  </label>

This component actually is input element. I dont want to handle all existing attributes of input. it is ridiculous.

<abt-float-input type='email' placeholder='email@example.com'>Email</abt-float-input>

Suppose I want to add maxlength attribute to abt-float-input as I know I should handle it as property in my custom element but I want to have it like Vue.

I rewrote one of my components with this feature in Vue.js.

How to do this? transfer any new/unhandled attributes to specific element of template.

I need when I write

<abt-float-input type='email' maxlength="10" placeholder='email@example.com'>Email</abt-float-input>

Aurelia transfers it automatically to input element like

 <label aut-uuid ref="floatInputLabel">
    <input id="${id}" maxlength="10"  ref="floatInput" class="${class}" css="${style}" type="${type}" placeholder="${placeholder}" />
    <span>
      <slot></slot>
    </span>
  </label>

Is it possible? If not I hope we have this feature in Aurelia vNext. It is very useful.


#2

The way it’s done in Aurelia is different, here is an example https://codesandbox.io/s/5v2r263wok

Note that there is no @bindable value, or @bindable placeholder from <my-text-area/>, but we can still bind outside view model directly to inside <textarea/>.

I’ve added some comment explaining why things are what they are, hope that can help understand how it works.


#3

Thanks,

If I get your point You bind every binable properties for the element.
I added maxlength to your my-text-area but nothing happens.

I expect to be able to add all the existing attributes to the element.


#4

When binding directly against a <textarea/>, Aurelia knows what property it should map attribute to: maxlength to maxLength, minlength to minLength etc… When binding through a layer like <my-text-area/>, it doesn’t have this knowledge. What you can do is to give Aurelia some more hint:

<my-text-area
  max-length.bind="10">

Edit: Or you can use the same attribute map, that Aurelia use internally to map from standard attributes (all lower case, to their corresponding property in camel case), then you can do:

<my-text-area
  maxlength.bind="10">

example: https://codesandbox.io/s/0q8j81zyw


#5

So cool, I think this should be a build-in feature in Aurelia vNext. It is very useful for creating new components. Helps us not reinvent the wheel and use existing attributes.

Because of this, In Aurelia-Toolbelt we had many problems until I saw the Vue.js technique and asked here.

Should I create an issue in Aurelia vNext repository?


#6

@bigopon

Unfortunately does not exist any doc about Aurelia framework secrets! :frowning:

Based on your code we want to create a customAttribute for this.

And use

image

Can you guide me about how to extend your snippet code as an customAttribute for using in all components and projects?


#7

Unfortunately does not exist any doc about Aurelia framework secrets!

Tbh, this is the first time I ever come across this, you helped me realized it’s possible. Thanks for this. I’ll probably write a small topic about it. Normally with Aurelia, you rarely ever need this.

For binding expressions, I’m not sure why it’s returning 0 for you, you can see it’s different here https://codesandbox.io/s/92wk0kl8w


#8

I think something happened wrong.

You assigned au-bind to your custom element. As you can see I assigned it to target input in my-textbox template. It says assign all attributes of <my-textbox></my-textbox> to this input element.

I need to access and pass targetInstruction.expressions of parent (in here <my-textbox></my-textbox>) in to child (target input). for using attributes of parent for child too.

I think child component can not access to parent expressions.

I created a repository here.


#9

Should I create an issue in Aurelia vNext repository?

Please do :slight_smile:
That would give us a more organized way of discussing and planning it as a potential built-in in the framework.


#10

@fkleuver

As you asked me, I created an issue here.


#11

I see what you meant to do. Here is an example of how to do that https://codesandbox.io/s/ymn81zzv19

Note that we are adding life cycle created to store reference to owning view of textarea because there is no way to walk up the scope from the custom aatribute. So the example works because the custom attribute assumes the custom elements that use it always have property named owningView pointing to that custom element owningView. This is only suitable for internal use.


#12

@bigopon

Thank you so much.

I came back with more questions!!! :relaxed::wink:

Your code works perfectly but mine not !

First, We transferred your code to Typescript equivalent but something does not work. See the sample

We bind it to a variable but does not work however it works on your sample perfectly. I am not sure what is wrong in Typescript version. Here is the repository

Second, Sometimes we need to transfer attributes not bind them however we can use X.one-time but it is not handy.

So I want to get other attributes and assign/transfer them to target element.


#13

You probaby didnt create created lifecycle in my textarea, also you need to store first parameter, known as owningView, in property owningView. For attributes without any binding (or plain attribute), i will need to have a look


#14

@bigopon

Yes you right

@customElement('my-textbox')
export class MyTextbox
{
    owningView: any;
    created(owningView) {
        this.owningView = owningView;
      }
}

It makes difficult to use. Everyone when using au-bind should know about above block of code and implement it.

Thanks for everything :heart_eyes::smiling_face_with_three_hearts::hugs:


#15

This is a must have built in I would say moving forward with vNext. It needs extended to include attributes on the parent element that are not bound, but that is minimal.