Premium support for our pure JavaScript UI components


Post by pmiklashevich »

Hi! In scheduler pro, how do I calculate a field value based on 2 other fields? Example:
duration field, foo field (number), bar field (number)
foo is from 0 to 10. bar is duration x foo. How do I configure data model?

I tried to specify a getter

  get bar() {
    return this.foo != null && this.duration != null ? this.foo * this.duration : null
  }

But that doesn't reactive. When I update foo, the bar is not updated.

convert function on a field doesn't have access to other fields in the record...

Is there a simple way to achieve it?

I also tried to use setters for duration and foo but got some TS errors

 'duration' is defined as a property in class 'EventModel', but is overridden here in 'SessionModel' as an accessor.

Appreciate your help. Cheers!

Pavlo Miklashevych
Sr. Frontend Developer


Post by arcady »

Hello Pavel,

You can use the Engine to do that.
In typescript the code might look like this:

class MyEventModel extends EventModel {

    @model_field({ 'type' : 'number', 'defaultValue' : 0 })
    bar          : Number

    @model_field({ 'type' : 'number', 'defaultValue' : 0 })
    foo          : Number

    @calculate('foo')
    * calculateFoo() {
        const bar = yield this.$.bar
        const duration = yield this.$.duration
        
        return foo * duration
    }

}

And if you deal with JavaScript then the code will look not that nice:

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};

class MyEventModel extends EventModel {

    * calculateFoo () {
        const bar = yield this.$.bar
        const duration = yield this.$.duration

        return bar * duration
    }

}

__decorate([ model_field({ type: 'number', defaultValue : 0 }) ], MyEventModel.prototype, 'bar', void 0);
__decorate([ model_field({ type: 'number', defaultValue : 0 }) ], MyEventModel.prototype, 'foo', void 0);
__decorate([ calculate('foo') ], MyEventModel.prototype, 'calculateFoo', void 0);

Post by pmiklashevich »

Thanks Arcady! I'll give it a try!

Pavlo Miklashevych
Sr. Frontend Developer


Post by pmiklashevich »

TypeScript version in the project I work on doesn't support decorators :) But nonetheless I will save your advice for further reference. Meanwhile I have found a workaround. If I call await eventRecord.setAsync('foo', value) then model fields are recalculated and task editor calls the bar's getter to get the value again. Which works since I have a getter specified which calculates the bar value. For duration it works out of the box.

Pavlo Miklashevych
Sr. Frontend Developer


Post Reply