11

This is a typical Angular's Material matInput:

<input matInput [(ngModel)]="model.property" name="property" />

Now to apply logic when the model changes, a common solution proposed by other developers in SO is to break banana-in-the-box into property-binder and event-hook expressions:

<input matInput [ngModel]="model.property" (ngModelChange)="model.property=someLogic($event)" />

Based on this logic, I created a digitGroup function that gets the input number, puts commas in between each three numbers, and shows that in the matInput field.

However, the problem is that now the model.property is a string representing the digit-grouped number, rather than being a real JavaScript number, so in each place I need to access its value and do some mathematical operation on it, I need to undigitGroup(model.property) first.

Is it possible that I bind matInput to two properties of the model at the same time? That way I can have model.property for calculations and model.digitGroupedProperty to show to the user, both at the same time.

3
  • Can't you bind it to an instance of a class containing the two properties? Commented May 21, 2018 at 7:44
  • Leaving angular apart, can you devise the spec for such a control ? Maybe what you need requires an extension of the matInput control, which can take more properties and can be binded separately Commented May 21, 2018 at 7:45
  • @Isma, that's an option of course, but it needs extra work for each input and for a total solution of an application including admin panel, and user panel forms, it's not a good solution. Besides, in short terms I want to be able to separate true value from shown value. This will make room for better UI design with less code. Commented May 21, 2018 at 7:47

2 Answers 2

5

You can use pipes to display the model transformed by digitGroup function without changing the model.

@Pipe({name: 'groupDigits'})
export class DigitGroupPipe implements PipeTransform {
  transform(value: any) {
      // Call your digitGroup() function here, then return result
  }
}

Then use them like this:

<input matInput [ngModel]="model.property | groupDigits" (ngModelChange)="model.property=$event" />

That way, your model will not be mutated by your digitGroup() function, only on the view

Sign up to request clarification or add additional context in comments.

Comments

3

As Jed Cua said, you should be able to do it with pipe. But you can also do it manually with a local variable, having the local variable for user display and model property for calculations.

  1. In your component, init a local variable modelPropertyRaw modelPropertyRaw = digitGroup(model.property) in ngOnInit
  2. Bind input to local variable modelPropertyRaw
  3. Add (input)="onPropertyChange($event.target.value)" to your input
  4. In onPropertyChange, do model.property = undigitGroup(modelPropertyRaw)

This separate true value from shown value.


EDIT: In your .html file

<!-- Replaced (ngOnModelChange) by (input). Notice that you are not forced to pass the event for the behavior we want -->
<input matInput [ngModel]="modelPropertyRaw" (input)="onPropertyChange($event.target.value)" />

In your .ts file

Add a local variable modelPropertyRaw (you can also add it as an attribute of your model class)

modelPropertyRaw: string;

Add onPropertyChange function like this

onPropertyChange(inputText: string)
{
  model.property = undigitGroup(modelPropertyRaw);
}

That's it ! If you don't want component local variable, add propertyRaw as an attribute of model and use it instead of modelPropertyRaw in this code

4 Comments

in item 1, did you mean model.modelPropertyRaw = digitGroup(model.property)?
Nope, because modelPropertyRaw is a local variable of your component, you could make a modelPropertyRaw attribute in your Model class, but if shown value is only used in one component, I'll definitely put it as an attribute of this component instead. (But there was also a little mistake in my post, I edited for more clarity)
I did what you said and couldn't make it work. I do really appreciate it if you provide a fiddler.
@mohammadrostamisiahgeli I edited my answer with some code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.