# Validate values of @bindable

**URL:** <https://discourse.aurelia.io/t/validate-values-of-bindable/2585>\
**Category:** Help Requests\
**Created:** [May 24, 2019, 2:17pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585 "2019-05-24T14:17:24Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jenselme](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jenselme/32/39_2.png) [@Jenselme](https://discourse.aurelia.io/u/Jenselme)\
**Post date:** [May 24, 2019, 2:17pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/1 "2019-05-24T14:17:24Z")

</div>

I wander if there is a mechanism similar to [PropTypes](https://reactjs.org/docs/typechecking-with-proptypes.html) to validate values of `@bindable`. I think Angular has something similar too. From time to time, passing the wrong value or forgot to passing a value (maybe because of a typo) is a source of bugs and frustration to understand what is going on.

Is this possible? If so how?

---

<div class="post-metadata">

**Author:** ![airboss001](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/airboss001/32/719_2.png) [@airboss001](https://discourse.aurelia.io/u/airboss001)\
**Post date:** [May 24, 2019, 2:28pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/2 "2019-05-24T14:28:52Z")

</div>

So educate me here, why use a bolt-on when it would seem you could use TypeScript to do that intrinsically? Is TS not an option?

---

<div class="post-metadata">

**Author:** ![Jenselme](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jenselme/32/39_2.png) [@Jenselme](https://discourse.aurelia.io/u/Jenselme)\
**Post date:** [May 24, 2019, 4:06pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/3 "2019-05-24T16:06:59Z")

</div>

1. My project is written in JS and I don’t intend to migrate to TypeScript soon. It would be nice to have some kind of check for this too (mostly to detect typos more easily).
2. It would also be nice to have this for single file components.
3. Bindable are passed to a component from the HTML like this `my-bindable.bind="value"` so the value is passed to the component at runtime. So I do know whether TS will be able to detect this since at this point, TS files are already compiled into JS files.

---

<div class="post-metadata">

**Author:** ![airboss001](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/airboss001/32/719_2.png) [@airboss001](https://discourse.aurelia.io/u/airboss001)\
**Post date:** [May 24, 2019, 4:58pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/4 "2019-05-24T16:58:25Z")

</div>

Thanks for that. Every project always has different needs and constraints of course so the reason for asking.  
Could you not perhaps use aurelia-validation as I think it can get fired when the binding changes to stay in the ecosystem?

---

<div class="post-metadata">

**Author:** ![Jenselme](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jenselme/32/39_2.png) [@Jenselme](https://discourse.aurelia.io/u/Jenselme)\
**Post date:** [May 25, 2019, 9:33am UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/5 "2019-05-25T09:33:05Z")

</div>

> [@airboss001](#):
>
> Could you not perhaps use aurelia-validation as I think it can get fired when the binding changes to stay in the ecosystem?

Maybe. I’ll try to look into that.

---

<div class="post-metadata">

**Author:** ![airboss001](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/airboss001/32/719_2.png) [@airboss001](https://discourse.aurelia.io/u/airboss001)\
**Post date:** [May 25, 2019, 12:28pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/6 "2019-05-25T12:28:12Z")

</div>

I use TS, but here is an example of how I am using it and it is working for me. Might not be the best way though.

In attached() I call a method setValidationRules() that setup the property validation requirements.  
Initially I was setting up a rules collection and running them against the property, but changed that over to use the on() method. I left the full function as it shows how I was able to use a few of the more advance methods.

```auto
setValidationRules()
    {
        const RENTAL_NOTSELECTED = 0;
        const NOINSTRUCTOR = 0;
        const RENTAL_DUAL = 3;

        //this.studentRules = 
        ValidationRules
            .ensure('wind').required()
            .ensure('expectedRunway').required()
            .ensure('fuelLeft').required()
            .ensure('fuelRight').required()
            .ensure('expectedFuelUsed').required()
            .ensure('weatherBriefed').satisfies((v, o: PaveTimecardData) =>
            {
                return o.weatherBriefed;
            })
            .on(this.paveTimecard.data);
            //.rules;

        //this.standardRules = 
        ValidationRules
            .ensure('airport').required()
            .ensure('aircraftId').required()
            .ensure('timecardDate').required()
            .ensure('hobbsStart').required()
            .ensure('hobbsEnd').required()
            .ensure('rentalTypeId').satisfies((val, o: PaveTimecardModel) =>
            {
                if (!o.rentalTypeId || o.rentalTypeId === RENTAL_NOTSELECTED)
                {
                    return false;
                }

                return true;
            })
            .withMessage("Rental Type needs to be selected.")
            .ensure('instructorId').satisfies((val, o: PaveTimecardModel) =>
            {
                if (o.instructorId === NOINSTRUCTOR)
                {
                    return false;
                }

                return true;
            })
            .withMessage("Rental Type [Dual] requires instructor to be selected.")
            .when((o: PaveTimecardModel) =>
            {
                return o.rentalTypeId === RENTAL_DUAL;
            })
            .ensure('instructorId').satisfies((val, o: PaveTimecardModel) =>
            {
                if (o.instructorId !== NOINSTRUCTOR)
                {
                    let msg: string = "Rental Type does not require an instructor to be selected and will be removed on save.";
                    if (this.warnings.indexOf(msg) === -1)
                    {
                        this.warnings.push(msg);
                    }
                    return true;
                }

                return true;
            })
            .when((o: PaveTimecardModel) =>
            {
                return o.rentalTypeId !== RENTAL_DUAL;
            })
            .ensure('fuelAmount').satisfies((val, o: PaveTimecardModel) =>
            {
                if (!o.fuelPurchased) 
                {
                    return true;
                }
                else if (o.fuelAmount && o.fuelAmount.length > 0)
                {
                    return true;
                }

                return false;
            })
            .when((o: PaveTimecardModel) => o.fuelPurchased)
            .withMessage("Purchased Fuel checked, no entry detected.")
            .on(this.paveTimecard);
            //.rules;
    }

```

I use it at various change events with the following code snippet:

```auto
        this.vcontroller.validate()
                .then(result => {
                    if(result.valid)
                        this.enableSaveTimecard = true;
                });

```

I have a repeat.for in the template that displays any errors in validation that require action:

```auto
            <div style="color: red;">
                <ul if.bind="vcontroller.errors">
                    <li repeat.for="error of vcontroller.errors">
                        ${error.message}
                    </li>
                </ul>
            </div>

```

Hope that helps somewhat.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [May 25, 2019, 1:29pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/7 "2019-05-25T13:29:01Z")

</div>

@Jenselme there is this plugin: [https://github.com/aurelia-contrib/aurelia-typed-observable-plugin](https://github.com/aurelia-contrib/aurelia-typed-observable-plugin) that can help you to process the value before it’s assigned to a view model. You can use it to implement your assertion:

```auto
import { bindable } from 'aurelia-typed-observable-plugin';

export class MyEl {
  @bindable({
    coerce: val => {
      const realValue = Number(val);
      if (typeof realValue !== 'number') {
        throw new Error('Invalid value for "myProp", given: ' + val);
      }
      return realValue;
    }
  })
  myProp
}

```

---

<div class="post-metadata">

**Author:** ![Jenselme](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jenselme/32/39_2.png) [@Jenselme](https://discourse.aurelia.io/u/Jenselme)\
**Post date:** [May 25, 2019, 2:26pm UTC](https://discourse.aurelia.io/t/validate-values-of-bindable/2585/8 "2019-05-25T14:26:05Z")

</div>

This looks exactly like what I need, thanks.
