Giter Club home page Giter Club logo

Comments (14)

sinan-can avatar sinan-can commented on July 16, 2024 1

Hi @travist

Thanks for this great library. It's exactly what we're looking for!

However, I am looking for a working custom component example, as well. I have been trying to render some html by a custom a component for 2 days with no luck.

Is it possible that you can extend the CustomComponent.ts file to make a small working example for us?

We appreciate it very much .
Thanks in advance!
Sinan

from angular-material.

sinan-can avatar sinan-can commented on July 16, 2024 1

Hello @JoeyHengst, @senvaitis,

this problem still occurs with the latest version. Did you find any solution or workaround to this problem?
I appreciate it a lot, if you can share your experience, solution or workaround, if you have any.

Thank you guys!
Best Regards

from angular-material.

travist avatar travist commented on July 16, 2024

You do not render with the Form.io component, but with this library, you actually render using the Angular Material component within the template construct of the @component. Like so....

@Component({
  template: '<-- HERE IS WHERE YOU RENDER YOUR COMPONENT -->'
})
export class MyCustomComponent extends MaterialComponent {
  ...
}

from angular-material.

senvaitis avatar senvaitis commented on July 16, 2024

I am also trying to render a custom component, however without success.

These are the changes I made:

  1. CustomComponent.ts:
import { Components, MaterialHtmlComponent } from 'angular-material-formio';
import HtmlComponent from 'formiojs/components/html/HTML.js';
import { Component } from '@angular/core';        // <--- ADDED
class HeaderComponent extends HtmlComponent {
  // Custom logic goes here.
}

@Component({   // <--- ADDED
  template: '<div>HALLO</div>'
})
export class MaterialHeaderComponent extends MaterialHtmlComponent {
  // Custom Material logic goes here.
}
(HeaderComponent as any).MaterialComponent = MaterialHeaderComponent;
Components.addComponent('header', HeaderComponent);
  1. app.component.html:
<mat-card>
  <!-- <mat-formio src="https://examples.form.io/kitchensink"></mat-formio> --> <!-- COMMENTED -->
  <mat-formio [form]="form"></mat-formio> <!-- UNCOMMENTED -->
</mat-card>

File app.component.ts is unchanged (tried changing/removing label, content, tag of header but no success):

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  form: any = {
    components: [
      {
        type: 'textfield',
        label: 'First Name',
        key: 'firstName'
      },
      {
        type: 'header',
        label: 'Header',
        content: 'This is a header',
        tag: 'h1'
      },
      {
        type: 'htmlelement',
        tag: 'strong',
        content: '{{ data.firstName }}',
        refreshOnChange: true,
        key: 'html'
      }
    ]
  };
  onSubmit(submission:any) {
    console.log(submission);
  }
}

This is what I see:
formio-custom-component

What should I do to get <div>HALLO</div> rendered?

from angular-material.

JoeyHengst avatar JoeyHengst commented on July 16, 2024

You do not render with the Form.io component, but with this library, you actually render using the Angular Material component within the template construct of the @component. Like so....

@Component({
  template: '<-- HERE IS WHERE YOU RENDER YOUR COMPONENT -->'
})
export class MyCustomComponent extends MaterialComponent {
  ...
}

I tried this approach but the html doesn't seem to get rendered. @travist

from angular-material.

travist avatar travist commented on July 16, 2024

Try with the latest version. I made a change to the HTMLComponent.

from angular-material.

JoeyHengst avatar JoeyHengst commented on July 16, 2024

@travist I tried this with the latest version but it didn't seem to work.
Screenshot 2019-10-24 at 19 58 59

import HtmlComponent from 'formiojs/components/html/HTML.js';
import { FormsHtmlComponent } from '../html/html.component';
import { Component } from '@angular/core';
const Components = require('formiojs/components/Components').default;

class HeaderComponent extends HtmlComponent {
  // Custom logic goes here.
}

@Component({
  template: '<p>HALLO</p>'
})
export class FormsCustomComponent extends FormsHtmlComponent {
  // Custom Material logic goes here.
}
(HeaderComponent as any).FormsComponent = FormsCustomComponent;
Components.addComponent('custom', HeaderComponent);

It's added to the index.ts to get rendered like :

import { FormsCustomComponent } from './custom/custom.component';

// Set the components.
const components: any = {
      ....
      custom: FormsCustomComponent
}

Results in the following error :
Screenshot 2019-10-24 at 20 06 40

from angular-material.

JoeyHengst avatar JoeyHengst commented on July 16, 2024

@travist Can you maybe take a look at this? Since with the Wizard now in place. Thank you for that btw. It's for us now useless if we can't render our own custom components which are made in FormManager.

For instance we have a custom address component which content managers can drag and drop in the FormManager to create forms.

The address component is composed of :
Panel
TextField
Column
TextField TextField
TextField
TextField

We now want to render this custom component but since we are getting the above error for a custom component. We are stuck.

from angular-material.

travist avatar travist commented on July 16, 2024

I believe it should be...

(HeaderComponent as any).MaterialComponent = FormsCustomComponent;

from angular-material.

JoeyHengst avatar JoeyHengst commented on July 16, 2024

I believe it should be...

(HeaderComponent as any).MaterialComponent = FormsCustomComponent;

Ah yeah we renamed MaterialComponent to FormsComponent.

But I think that’s not the issue we even tried it out with a fresh checkout with the demo project and then a wizard form which contained a customcomponent without renaming anything but just use our own form in the <mat-formio>. And we didn’t got our html being rendered. The customcomponent was detected but it didn’t show us our html we had in the template.

from angular-material.

travist avatar travist commented on July 16, 2024

There is really nothing different between a custom component and a regular component. The ONLY thing different is that you need to ensure you register the component using

Formio.Components.addComponent('custom', CustomComponent);

It could be that when you are getting the Components from formiojs that you are including the wrong module that the application is not using. I have seen this before... You may try doing this...

import { Formio } from 'angular-formio';

And then

Formio.Components.addComponent(....);

If this does not work, then try importing from formiojs. If that does not work, then try importing from angular-material-formio like this.

import { Formio } from 'angular-material-formio';

It may take some trial and error since it is hard to know which Formio.js library is getting imported by your application if there are multiple instances of the library getting pulled in.

from angular-material.

enigmatic avatar enigmatic commented on July 16, 2024

Using https://github.com/formio/angular-material-formio/blob/master/projects/angular-material-formio/src/lib/components/index.ts as a guide here's what I have that seems to work:

replace
(HeaderComponent as any).MaterialComponent = HeaderComponent;

with

const CompClass = (HeaderComponent as any);
CompClass.MaterialComponent = MaterialHeaderComponent;
CompClass.prototype.render = (function () {
  if (this.materialComponent) {
    return this.materialComponent;
  }
  const viewContainer = this.parent ? this.parent.viewContainer(this) : this.viewContainer(this);
  if (!viewContainer) {
    return;
  }
  const factory = this.options.viewResolver.resolveComponentFactory(CompClass.MaterialComponent);
  const componentRef = viewContainer.createComponent(factory);
  (componentRef.instance as any).setInstance(this);
});

const setValue = CompClass.prototype.setValue;
CompClass.prototype.setValue = (function (...args) {
  if (this.materialComponent) {
    this.materialComponent.setValue(args[0]);
  }
  return setValue.call(this, ...args);
});

Then follow @travist use of the Angular @Component template to add your code. I think you can treat it as a regular Angular component from here out.

The library doesn't seem to update the renderer to the MaterialComponent automatically. There is probably a need for a angular-material-formio addComponent wrapper that does this, and I may work towards something like this as I get more comfortable with the library (assuming this isn't moot thanks to the Angular 9 upgrades).

from angular-material.

sinan-can avatar sinan-can commented on July 16, 2024

Hi @enigmatic,

thank you for the long explanation and sample code. I have done it as you described but with no luck. Nothing will be rendered. I have debugged a litte bit and I have realised that a renderComponent of HeaderComponent will be called with empty body.

image

Here is my final code:

import { Components, MaterialHtmlComponent } from 'angular-material-formio';
import HtmlComponent from 'formiojs/components/html/HTML.js';
import {Component} from '@angular/core';

export class HeaderComponent extends HtmlComponent {
    // Custom logic goes here.
}

@Component({
    template: '<div>dropzone comes here</div>'
})
export class MaterialHeaderComponent extends MaterialHtmlComponent {
    // Custom Material logic goes here.
}

const CompClass = (HeaderComponent as any);
CompClass.MaterialComponent = MaterialHeaderComponent;
CompClass.prototype.render = (function () {
    if (this.materialComponent) {
        return this.materialComponent;
    }
    const viewContainer = this.parent ? this.parent.viewContainer(this) : this.viewContainer(this);
    if (!viewContainer) {
        return;
    }
    const factory = this.options.viewResolver.resolveComponentFactory(CompClass.MaterialComponent);
    const componentRef = viewContainer.createComponent(factory);
    (componentRef.instance as any).setInstance(this);
});

const setValue = CompClass.prototype.setValue;
CompClass.prototype.setValue = (function (...args) {
    if (this.materialComponent) {
        this.materialComponent.setValue(args[0]);
    }
    return setValue.call(this, ...args);
});

Components.addComponent('dropzone', HeaderComponent);

Do I miss here anything?

I registered MaterialHeaderComponent in entryComponents of app.module. Otherwise angular complains as follows:

ERROR Error: No component factory found for MaterialHeaderComponent. Did you add it to @NgModule.entryComponents?

from angular-material.

enigmatic avatar enigmatic commented on July 16, 2024

Odd. It works for me. I did get an error MaterialHeaderComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'nativeElement' of undefined when extending MaterialHtmlComponent, so you can extend the new Component from MaterialComponent:

export class MaterialHeaderComponent extends MaterialComponent {
    // Custom Material logic goes here.
}

The empty renderComponents function comes from MaterialComponent and shouldn't have any impact on the custom component.

Here's the full project: https://github.com/enigmatic/angular-material-formio-demo

from angular-material.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.