Closed dinbtechit closed 1 month ago
I had this question too, and no one answered.
The solution I came up with was to create a global service, and within it there are methods for adding and viewing the main instance.
In the formiobasecomponent component within the createRenderer function, I called the add method of the service I created.
createRenderer() {
const Renderer = this.getRenderer();
const form = (new Renderer(
this.formioElement ? this.formioElement.nativeElement : null,
this.form,
this.getRendererOptions()
));
// adicionado-inicio
this.formFormioService.setEstruturaComponenteFormularioRender(form);
// adicionado-fim
return form.instance;
}
In custom components, I injected this global service and viewed the instance that way.
It worked, I hope it helps you.
Can you explain more @adhonay how you are storing this and how you will get the same instance? It will be very helpful.
Você pode explicar mais@adhonaycomo você está armazenando isso e como obterá a mesma instância? Será muito útil.
Ignore the main and secondary instance part, in your case it will probably only be 1 instance. I did it this way, because I am using modals from one instance within another.
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { ConstantesSistemaFormio } from '../constantes/constantes-sistema-formio';
@Injectable({
providedIn: 'root'
})
export class FormFormioService {
private estruturaComponenteFormularioRenderInstanciaPrincipal = new BehaviorSubject<object>(undefined);
private estruturaComponenteFormularioRenderInstanciaSecundariaGrid = new BehaviorSubject<object>(undefined);
constructor() { }
private quantidadeInstaciasFormioRender(): number {
return document.querySelectorAll(ConstantesSistemaFormio.tceFormio)?.length;
}
public existeInstanciaRenderFormio(): boolean {
return this.quantidadeInstaciasFormioRender() > 0
}
public existeInstanciaSecundariaGridAberta(): boolean {
return this.quantidadeInstaciasFormioRender() === 2
}
public setEstruturaComponenteFormularioRender(instancia) {
if (instancia && this.quantidadeInstaciasFormioRender() <= 1) {
this.estruturaComponenteFormularioRenderInstanciaPrincipal.next(instancia);
} else if (instancia && this.quantidadeInstaciasFormioRender() === 2) {
this.estruturaComponenteFormularioRenderInstanciaSecundariaGrid.next(instancia);
}
}
public getEstruturaComponenteFormularioRenderInstanciaPrincipal(): object {
return this.estruturaComponenteFormularioRenderInstanciaPrincipal.value;
}
public getEstruturaComponenteFormularioRenderInstanciaSecundariaGrid(): object {
return this.estruturaComponenteFormularioRenderInstanciaSecundariaGrid.value;
}
}
Can you show the createRenderer class aswell how you are extending the class.?
Você pode explicar mais@adhonaycomo você está armazenando isso e como obterá a mesma instância? Será muito útil.
Ignore the main and secondary instance part, in your case it will probably only be 1 instance. I did it this way, because I am using modals from one instance within another.
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { ConstantesSistemaFormio } from '../constantes/constantes-sistema-formio'; @Injectable({ providedIn: 'root' }) export class FormFormioService { private estruturaComponenteFormularioRenderInstanciaPrincipal = new BehaviorSubject<object>(undefined); private estruturaComponenteFormularioRenderInstanciaSecundariaGrid = new BehaviorSubject<object>(undefined); constructor() { } private quantidadeInstaciasFormioRender(): number { return document.querySelectorAll(ConstantesSistemaFormio.tceFormio)?.length; } public existeInstanciaRenderFormio(): boolean { return this.quantidadeInstaciasFormioRender() > 0 } public existeInstanciaSecundariaGridAberta(): boolean { return this.quantidadeInstaciasFormioRender() === 2 } public setEstruturaComponenteFormularioRender(instancia) { if (instancia && this.quantidadeInstaciasFormioRender() <= 1) { this.estruturaComponenteFormularioRenderInstanciaPrincipal.next(instancia); } else if (instancia && this.quantidadeInstaciasFormioRender() === 2) { this.estruturaComponenteFormularioRenderInstanciaSecundariaGrid.next(instancia); } } public getEstruturaComponenteFormularioRenderInstanciaPrincipal(): object { return this.estruturaComponenteFormularioRenderInstanciaPrincipal.value; } public getEstruturaComponenteFormularioRenderInstanciaSecundariaGrid(): object { return this.estruturaComponenteFormularioRenderInstanciaSecundariaGrid.value; } }
I am not able to get instance when i invoke setInstance(), or either calling createRenderer() from constructor in my custom component using reference from code snippet you provided , so could you please provide your custom component with the proper place where you are getting the instance ? or you can send across the files which have the running code. (Note: We have tried all possible ways to get instance and we have angular cli 16 as a mandatory platform.)
By extending MaterialComponent class i am able to get the instance of the custom component with setInstance() in one project but in another project without using angular material and considering typescript and angular(angular material excluded ) setup, which class i can extend/implement to achieve similar behavior?
Hi @dinbtechit
Did you find any solution?
@pradeepsonisoni - I have not. I think the custom component has some issues with the way how it implemented updating the component value. Also, starting from version Formio/angular version 6.0.0 the custom components are being deprecated all together. So it may be worth forking the custom component code and adding it to your own angular project. That way, you will have more control over the code or at least that's what I am going to be doing to fix this issue.
@dinbtechit Thank you for quick reply.
Você pode mostrar a classe createRenderer também como está estendendo a classe?
createRenderer is a method already implemented by formio itself in the formiobasecomponent.ts component
@adhonay If you are able to get the instance. you can share the code how you are implementing the FormioCustomComponent class. let us know because We are not getting the instance.
@adhonaySe você conseguir obter a instância. você pode compartilhar o código como está implementando a classe FormioCustomComponent . deixe-nos saber porque não estamos recebendo a instância.
FormioCustomComponent here is a simple interface, created in the Angular template.
export interface FormioCustomComponent<T> {
value: T; // Should be an @Input
valueChange: EventEmitter<T>; // Should be an @Output
disabled: boolean;
formioEvent?: EventEmitter<FormioEvent>; // Should be an @Output
}
You don't need anything more than:
1- Create the service as I sent above.
2- Insert the line below into the createRenderer function in formiobasecomponent.ts to send the instance.
this.formFormioService.setEstruturaComponenteFormularioRender(form);
3- In your CustomComponent, inject the service into the constructor and then wherever you want in the component, use the line:
let instanciaRender = this.formFormioService.getEstruturaComponenteFormularioRenderInstanciaPrincipal();
@adhonay If we have two instance of the same custom component. Is it working with two instance? I don't think so.
I had this question too, and no one answered.
The solution I came up with was to create a global service, and within it there are methods for adding and viewing the main instance.
In the formiobasecomponent component within the createRenderer function, I called the add method of the service I created.
createRenderer() { const Renderer = this.getRenderer(); const form = (new Renderer( this.formioElement ? this.formioElement.nativeElement : null, this.form, this.getRendererOptions() )); // adicionado-inicio this.formFormioService.setEstruturaComponenteFormularioRender(form); // adicionado-fim return form.instance; }
In custom components, I injected this global service and viewed the instance that way.
It worked, I hope it helps you.
@adhonay - isn't the formiobasecomponent class part the npm package, how did you manage to update the createRenderer()
method to inject the code - > this.formFormioService.setEstruturaComponenteFormularioRender(form);
?
I had this question too, and no one answered. The solution I came up with was to create a global service, and within it there are methods for adding and viewing the main instance. In the formiobasecomponent component within the createRenderer function, I called the add method of the service I created.
createRenderer() { const Renderer = this.getRenderer(); const form = (new Renderer( this.formioElement ? this.formioElement.nativeElement : null, this.form, this.getRendererOptions() )); // adicionado-inicio this.formFormioService.setEstruturaComponenteFormularioRender(form); // adicionado-fim return form.instance; }
In custom components, I injected this global service and viewed the instance that way. It worked, I hope it helps you.
@adhonay - isn't the formiobasecomponent class part the npm package, how did you manage to update the
createRenderer()
method to inject the code - >this.formFormioService.setEstruturaComponenteFormularioRender(form);
?
I cloned the git project and started implementing custom components from it.
You can modify the createRenderer method because you have direct access to it.
https://github.com/formio/angular/blob/master/projects/angular-formio/src/FormioBaseComponent.ts
Line 108
Thanks @adhonay, that makes sense now. Actually, a better approach would be to fork the custom component and modify the logic there.
https://github.com/formio/angular/tree/5.5.x/projects/angular-formio/src/custom-component
It seems a resolution has been provided by the community so I'm going to go ahead and close it but can re-open if someone needs to contribute more here.
For the folks who are still looking for a solution. I ended up creating an Angular Service and maintain the state there. Here is a pseudo code
@Injectable({for: 'root'})
export class MyCompService {
string buttonTextState = ''; // default empty
}
@Component({...})
export class MyComponent implement FormIoCustomComponent, OnInit, AfterViewInit {
@Input() buttonText: string;
myCompService = inject<MyCompService>();
ngOnInit() {
if (!buttonText && !this.myCompService.buttonTextState) {
// Read the buttonText from the state service variable before the component is loaded
this.buttonText = this.myCompService.buttonTextState;
}
}
ngAfterViewInit() {
// store Button Text in the service.
if (buttonText) {
this.myCompService.buttonTextState = this.buttonText;
}
}
}
Is it possible to access the current instance of the Formio Component within the custom component?
I would like to access the component because the customOptions are not accessible during initialization. Furthermore, dragging the component does not preserve any of the customOptions.