Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot bind initial data to form controls #173

Closed
alemputes opened this issue May 11, 2020 · 10 comments
Closed

Cannot bind initial data to form controls #173

alemputes opened this issue May 11, 2020 · 10 comments
Labels
flag: can be closed? This issue or PR should probably be closed now type: RFC/discussion/question This issue is about RFC, discussion or a question

Comments

@alemputes
Copy link

alemputes commented May 11, 2020

Trying to fill the data coming from my backend so it's prepopulated

@Component({
	selector: 'app-my-profile',
	templateUrl: './my-profile.component.html',
	styleUrls: [ './my-profile.component.scss' ],
	// providers: [subformComponentProviders(MyProfileComponent)],
	// changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyProfileComponent extends NgxRootFormComponent<Customer> implements OnInit {
	constructor() {
		super();
	}

	@DataInput() 
	@Input('customer') dataInput: Required<Customer> | null | undefined;

	dataOutput: EventEmitter<CustomerCardForm>;

	ngOnInit(): void {
		console.log(this.dataInput); // always undefined
	}

	protected getFormControls(): Controls<Customer> {
		console.log(this.dataInput); // always undefined
		return {
			no: new FormControl({ value: 'Test', disabled: true }, Validators.required),
		}
	}
}
export interface Customer {
	no: string
}

Container

customer$: Observable<Customer>;
this.customer$ = this.customerService.get(); // returns Observable<Customer>

// Also try ed
customer$: Subject<CustomerCardForm> = new Subject();

this.customerService.get().subscribe((customer) => {
   this.customer$.next(customer);
});

Container html:
<app-my-profile [customer]='customer$ | async'></app-my-profile>

@maxime1992
Copy link
Contributor

Is there a question here?

Also, please consider making a stackblitz if possible 👍

@maxime1992 maxime1992 added the type: RFC/discussion/question This issue is about RFC, discussion or a question label May 11, 2020
@alemputes
Copy link
Author

alemputes commented May 11, 2020

Hi Max, yeah sorry, why is the value of the dataInput always undefined in both ngonInit and getFormsControl? In getFormsControl I need to set the initial data coming from the source instead of the 'Test' value I have added.

If I change it to normal Input I get all the data but still the getFormsControl does not have access to this data, it's undefinied.

	_customer: Required<Customer> | null | undefined;
	@Input() set customer(value: Customer) {
		if (value) {
			this._customer = value;
		}
	}

@maxime1992
Copy link
Contributor

Hi 👋! Oh that's the beauty of this 😄

You don't have to do it manually 👍 ! Ngx sub form takes care of that for you.

Just do

@Component({
  selector: 'app-my-profile',
  templateUrl: './my-profile.component.html',
  styleUrls: ['./my-profile.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyProfileComponent extends NgxRootFormComponent<Customer> {
  @DataInput()
  @Input('customer')
  dataInput: Required<Customer> | null | undefined;

  @Output('customerUpdate')
  dataOutput: EventEmitter<CustomerCardForm>;

  protected getFormControls(): Controls<Customer> {
    return {
      no: new FormControl(null, Validators.required),
    };
  }
}

Any time the data input changes, ngx-sub-form will update the inner form.

@alemputes
Copy link
Author

alemputes commented May 11, 2020

Wow, knew I screwed up somewhere hehe. I accidentally stumbled on this library and man I am glad, it's soo freaking good, big thumbs up for your great work and thanks for your fast answers.

Now I just wish I had a great library like this to reduce the html boilerplate code as well, maybe you can point me in right direction? :) I am now using this method:

<form [formGroup]="formGroup">
        <app-input [controlName]="formControlNames.customerNo" label="Kundnummer"></app-input>
</form>

Input component:

@Component({
  selector: 'app-input',
  template: `
    <div class="p-grid">
      <div class="p-col-12 p-md-3">{{ label }}</div>
      <div class="p-col-12 p-md-6">
        <input [formControlName]="controlName" [type]="type" [placeholder]="placeholder" pInputText />
      </div>
	    <div class="p-col-12 p-md-3">
        <p-message
          severity="error"
          text="{{errorMessage}}"
          *ngIf="isInvalid">
        </p-message>
	    </div>
    </div>
  `,
  styleUrls: ['./input.component.css'],
  viewProviders: [
    {
      provide: ControlContainer,
      useFactory: (container: ControlContainer) => container,
      deps: [[new SkipSelf(), ControlContainer]]
    }
  ]
})
export class InputComponent implements OnInit {
  constructor() {}

  @Input() controlName: string;

  @Input() type = 'text';
  @Input() label: '';
  @Input() placeholder = '';
  
  @Input() errorMessage = '';
  @Input() isInvalid = false;
}

@maxime1992
Copy link
Contributor

maxime1992 commented May 11, 2020

I accidentally stumbled on this library and man I am glad, it's soo freaking good, big thumbs up for your great work and thanks for your fast answers

Thanks for the kind words!

If you feel like sharing this here #112 (and maybe tell us more about your usage) that'd be fantastic :)

The example you pasted above is a bit weird as you don't have any form group and you're not using ngx-sub-form at all in the input component?

Unsure whether it'll actually help or not but you can look this issue #159 and the stackblitz I made at the end. I don't think you can reduce boilerplate much more than that.

@maxime1992 maxime1992 added the flag: can be closed? This issue or PR should probably be closed now label May 11, 2020
@alemputes
Copy link
Author

The whole purpose of the InputComponent is to hold some boilerplate code for label, control, error messages, because these three pieces typically are compounded together and I get the same design for it all over the application. This is not done with ngx-sub-form, I am instead using it like in this post: https://stackoverflow.com/questions/52893088/forwarding-formcontrolname-to-inner-component-in-angular

Maybe I could move this to a ngx-sub-form component but having a single control in a ngx-sub-form just to get the desired design, I don't know what benefits I would get over this approach I am using right now.

@maxime1992
Copy link
Contributor

Right. I feel like this is getting a bit off track from ngx-sub-form and that I replied to your initial issue.

If you've got concerns about the boilerplate of your last comment maybe raise a question on stackoverflow?

I'm going to go ahead and close this issue now but if you feel like I haven't replied on something ngx-sub-form related please reopen or open a new issue 😸!

@alemputes
Copy link
Author

Sorry if I got off topic here, just wanted to answer your question. You can close it and thanks for all your help, really appreciate it :)

@m12lrpv
Copy link

m12lrpv commented Sep 27, 2021

There's an aspect of this that is a problem.

It's great that datainput is passed through to the child form.

What if we want to access it in the root form? We can't do that if it's always undefined.

and dataInput$ is protected so it's useless also

@maxime1992
Copy link
Contributor

This should be irrelevant in the new version (currently in BETA). It's available on NPM but the doc wasn't updated just yet. API doesn't change a lot so if you're familiar with ngx-sub-form and you want to give it a spin you can look at this branch: https://github.com/cloudnc/ngx-sub-form/tree/feat-rewrite

We've created an entirely new folder and rewrote our demo app to use the new syntax so it's actually really easy to compare between the old API and the new one. Here's the folder: https://github.com/cloudnc/ngx-sub-form/tree/feat-rewrite/src/app

main folder is where the app using the old API is, main-rewrite is the one with the same entired sub form, but using the new API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flag: can be closed? This issue or PR should probably be closed now type: RFC/discussion/question This issue is about RFC, discussion or a question
Projects
None yet
Development

No branches or pull requests

3 participants