I don't understand why do you need an Input property value for your custom Input from the parent. (Probably you want some default value?).
Coming to the solution of your question. Why is your view(input box) not updating even if the model has the correct maximum value? Let's see it this way:
You have a property value which is bound to the input box. So when the input value changes, this is how value's data will be updated. Consider that initially value = 0, then you input 1 in the input box, due to 2-way binding, value will be updated with one. Will it be marked for change detection here? Yes! And this will again update the Input Box on Change Detection cycle. Now, you input 2(input box now contains 12). Again It will be marked for Change Detection. Now, you input 3(The input should had contained 123) but because of your logic, it is changed to 99. So what changes actually? The data in the value property. Now your input box contains 99. You enter another 0. What happens? Your setter logic will make value to 99.(But wait it was already 99). So Is is it marked for Change detection? No. So will the Input which is bound to value see any difference? No.
Note: At least one change detection cycle should run on all your input events in the input box.
How I solved your problem is (I have used property data instead of value):
constructor(private _cdr: ChangeDetectorRef) {}
@Input() set data(v) {
this._v = v; // I am assigning whatever value I get to the data property
// so that in the manual change detection a change can be seen
// (even though that change doesn't need to be show)
this._cdr.detectChanges();
if (v > 99) {
v = 99
}
else if (v < 0) {
v = 0
}
this._v = v
this.valueChange.emit(v);
}
In the very first step, I am assigning whatever value I get from the input box to _v, then I call a manual change detection before proceeding with my logic. So the value of data is updated with the Input Value. My logic will revert it back to 99 or 0, it will be marked for change detection now, and your view will be updated apprpriately (Note: Your output will emit the final value itself.)
See the working example here: https://stackblitz.com/edit/angular-custom-number-input?file=src/app/hello.component.ts