Use Shoelace in Aurelia 2 , the sl-input component value.two-way binding cause an error

I’m using Shoelace in a Aurelia 2 app . The ‘sl-input’ component value.two-way binding cause an error.
here is the code and errors.

 <sl-input label="phone"  value.two-way="user.phone" ></sl-input>

error:

utilities.ts:22 Uncaught (in promise) Error: Trying to set value for property value in dirty checker
    at createError (utilities.ts:22:49)
    at DirtyCheckProperty.setValue (dirty-checker.ts:142:11)
    at PropertyBinding.updateTarget (property-binding.ts:74:27)
    at PropertyBinding.bind (property-binding.ts:144:12)
    at Controller.bind (controller.ts:609:26)
    at Controller.activate (controller.ts:593:10)
    at ComponentAgent.Mt (component-agent.ts:69:31)
    at viewport-agent.ts:523:38
    at Transition.Qt (router.ts:81:19)
    at viewport-agent.ts:521:18

If I use ‘value.bind’ or ‘value.from-view’, it works as expected. ‘value.bind’ works the same as ‘value.one-way’ in this case.

Any one can help?

It should be similar like the integration of other lib mentioned here Integration | The Aurelia 2 Docs

Thanks! The microsoft FAST example works well! Here is the code for shoelace in case others might need it.(not fully tested):

const shoelaceAdapter = (container) => {
  const attrMapper = container.get(IAttrMapper);
  const nodeObserverLocator = container.get(NodeObserverLocator);
  attrMapper.useTwoWay((el, property) => {
    switch (el.tagName) {
      case 'SL-INPUT':
      case 'SL-SELECT':
      case 'SL-TEXTAREA':
      case 'SL-RADIO':
      case 'SL-RADIO-GROUP':
        return property === 'value';
      case 'SL-CHECKBOX':
      case 'SL-SWITCH':
        return property === 'checked';
      case 'SL-TAB':
        return property === 'active';
      default:
        return false;
    }
  });

  // Teach Aurelia what events to use to observe properties of elements.
  // Because FAST components all use a single change event to notify,
  // we can use a single common object
  const valuePropertyConfig = { events: ['sl-input', 'sl-change'] };
  nodeObserverLocator.useConfig({
    'SL-CHECKBOX': {
      checked: valuePropertyConfig
    },
    'SL-RADIO': {
      value: valuePropertyConfig
    },
    'SL-RADIO-GROUP': {
      value: valuePropertyConfig
    },
    'SL-INPUT': {
      value: valuePropertyConfig
    },
    'SL-SWITCH': {
      checked: valuePropertyConfig
    },
    'SL-TAB': {
      active: valuePropertyConfig
    },
    'SL-SELECT': {
      value: valuePropertyConfig
    },
    'SL-TEXTAREA': {
      value: valuePropertyConfig
    }
  })
}

Aurelia
  .register(AppTask.creating(IContainer, shoelaceAdapter))
  .app(MyApp)
  .start();

I have also tried the Ionic example , It didn’t work. I have noticed that the only difference lies in the registration part. FYI.

This does NOT work:

export class ShoelaceFramework implements IRegistry {
  register(container: IContainer) {
      const attrMapper = container.get(IAttrMapper);
      const nodeObserverLocator = container.get(NodeObserverLocator);
      attrMapper.useTwoWay((el, property) => {
        console.log("two way bind...");
        
          if (el.tagName === 'SL-CHECKBOX' ||
              el.tagName === 'SL-TOGGLE'
          ) {
              return property === 'checked';
          }

          return el.tagName.startsWith('SL') && property === 'value';
      });
      const valuePropertyConfig = { events: ['sl-input','sl-change'] };
      nodeObserverLocator.useConfig({
          'SL-INPUT': {
              value: valuePropertyConfig
          }
      });
      return container;
  }
}

Aurelia
.register(ShoelaceFramework)
  .app(MyApp)
  .start();
2 Likes

@zhanglongyu can you help with a PR to add an example of shoelace integration to the doc? Will definitely be welcomed and a source of help for others.

I would love to do that, but I am not familiar with PR process. I read the contributor guide, still don’t know where to start. :smile: