0

I have this pipe, secondsToHms, to convert from seconds to hours, minutes and seconds:

transform(seconds: number): string {
  const minutes = Math.floor(seconds / 60); //minutes
  const secs = seconds % 60; //seconds
  const hours = Math.floor(minutes / 60); //hours
  const mins = minutes % 60; //minutes

  return (
    '' +
    (hours < 10 ? hours.toString().padStart(2, '0') : hours.toString()) +
    mins.toString().padStart(2, '0') +
    secs.toString().padStart(2, '0')
  );
}

In my HTML, I'm trying to display the value like this, but the time doesn't display as I want (HH:mm:ss) and I don't know why. I'm using ngx-mask inside the input.

<ng-template [ngIf]="control.value.type === 'TYPE1'">
   <div class="input-group mb-2">
     <input
       (ngModelChange)="setDirty(true)"
       formControlName="quantity"
       type="text"
       class="form-control text-center"
       placeholder="00:00:00"
       mask="00:m0:s0"
      [value]="control.value.quantity | secondsToHms"
     />
  </div>
</ng-template>

The control variable is accessing in the template via this loop:

<ng-container *ngFor="let control of dataArr.controls; 
  let i = index">

And this is the dataArr function:

get dataArr() {
  return this.myForm.get('allData') as FormArray;
}

I need to do the conversion in the template since the pipe only applies when type is equal to TYPE1 which only happens here [ngIf]="control.value.type === 'TYPE1'".

I'm using this function to create form controls, don't know if it's relevant to this case.

addDataFormGroup(data: DataModel) {
  this.dataArr.push(
    this.fb.group({
      data: data.data,
      dataType: data.dataType,
      quantity: data.quantity,
    })
  );
}
jgcarrillo
  • 148
  • 11

1 Answers1

0

there're several errors in your code.

  1. The mask that use ngx-mask should be: 00:00:00

  2. When you use ReactiveForms (formControlName) you should not use value. You need give value to the formControl -using patchValue or setValue-, so to give value you use a simple function, not a pipe

  3. You can make more compact your function

    transform(seconds: number):string {   
        const minutes = Math.floor(seconds / 60); //minutes  
        const secs = seconds % 60; //seconds   const hours =
        Math.floor(minutes / 60); //hours   const mins = minutes % 60;
        //minutes
    
          return ('00'+hours).slice(-2)+":"+
                 ('00'+mins).slice(-2)+":"+
                 ('00'+secs).slice(-2) }
    
    //and you use addDataFormGroup(data: DataModel) {
         this.dataArr.push(
            this.fb.group({
              data: data.data,
              dataType: data.dataType,
              quantity: this.transform(data.quantity), //<--here
            })   
          ); }
    

Update As the trasnformations depend from a variable we can take another appoach that is use [ngModel] and (ngModelChange) to mannage a formControl.

Imagine a functions like:

  transform(seconds: number|string): string {
    if (typeof(seconds)=="string")
      return seconds;
    const minutes = Math.floor(seconds / 60); //minutes
    const secs = seconds % 60; //seconds
    const hours = Math.floor(minutes / 60); //hours
    const mins = minutes % 60; //minutes
  
    return ('00'+hours).slice(-2)+":"+
           ('00'+mins).slice(-2)+":"+
           ('00'+secs).slice(-2)
  }
  parse(value:string)
  {
    const match=value.match(/\d\d/g)
    if (match && match.length==3)
      return (+match[0])*3600+(+match[1]*60)+(+match[2])
    return value
  }

We can use some like

<form [formGroup]="form">
  <div formArrayName="dataArray">
    <div *ngFor="let group of dataArray.controls;let i=index" [formGroupName]="i">
    <input [ngModel]="transform(form.get('dataArray.'+i+'.quantity').value)"
           (ngModelChange)="form.get('dataArray.'+i+'.quantity')
                                .setValue(parse($event))"

           [ngModelOptions]="{standalone:true}"
    />
    </div>
  </div>
</form>

See that we use [ngModel] to show the value of the formControl and ngModelChange to change the value of the formControl. Perhafs it's necesary some ajust when (blur) the input

You have a litle stackblitz here

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Okay, I got it, but in my case I need to use the pipe because the data depends on a select so I cannot apply the `secondsToHms` function (or pipe) to all the quantities. – jgcarrillo Mar 13 '23 at 09:15
  • @jgcarrillo, thre're a nother option that it's use [ngModel] and (ngModelChange) to mannage the FormControl. I just updated the answer – Eliseo Mar 13 '23 at 11:11
  • Thanks very much for the help but with that approach I cannot watch the `ng-dirty` class so although I submit the form, the input still remain dirty. – jgcarrillo Mar 13 '23 at 11:32
  • @jgcarrillom a formControl exist even there're no input with formcontrolName. I imagine you can add to the input with ngModel some like [ngClass]="{'ng-dirty':form.get('dataArray.'+i+'.quantity').dirty,'ng-touched':form.get('dataArray.'+i+'.quantity').touched...}" But I'm not pretty sure about this – Eliseo Mar 13 '23 at 11:40
  • I think I can't. I have tried before with that solution and the input is still dirty. – jgcarrillo Mar 13 '23 at 11:51