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

Generate components #91

Open
bengry opened this issue Feb 17, 2019 · 4 comments
Open

Generate components #91

bengry opened this issue Feb 17, 2019 · 4 comments
Labels
help wanted Extra attention is needed pinned

Comments

@bengry
Copy link
Contributor

bengry commented Feb 17, 2019

The issue

Currently creating @angular-react components is done manually, specially in @angular-react/fabric (but the same holds true for any library implementation).
This is fine for a few components, and didn't prove to be worth the effort of creating such a tool, but as the library grows, and more components are added - this seems like it would simplify the long-term maintenance, especially in regards to upgrading the underlying React UI framework (e.g. office-ui-fabric-react, Semantic-UI-React).

Proposed solution

There are a number of ways to go about this, but the most likely is to use Angular Schematics to generate components, which as part of the inputs will take some sort of identifier for a *Props interface (e.g. ICheckboxProps), and together with the TypeScript compiler API (or any of its wrappers) and add the relevant Inputs and Outputs for the component, as well as bindings for the template etc.:

  1. Props that are of type string | number | boolean | object should be added as-is. e.g: componentRef?: IRefObject<ICheckbox> -> @Input() componentRef?: ICheckboxProps['componentRef']
  2. Props that conform to (...args: any[]) => void should be added as @Outputs, with the arguments added as an object with properties the same name as the function parameters. e.g.: onChange?: (ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean) => void -> @Output() readonly onChange = new EventEmitter<{ ev?: Event, checked?: boolean }>().
  3. Props that confirm to (...args: any[]) => *non-void* should be added as-is (see 1. above), also as @Inputs.
  4. Props that are of type IRenderFunction<T> should be added as InputRendererOptions<T>. If the prop name is prefixed with an on, omit it (the Angular doesn't let Inputs be prefixed with on), and camel-cased. e.g.:
    onRenderNavigation?: IRenderFunction<IPanelProps> -> @Input() renderNavigation?: InputRendererOptions<IPanelProps>.
  5. (optional) copy the JDoc as-is.

Open issues:

  • The proposed solution is very specific to office-ui-fabric-react, as this is the only actively-maintained package wrapper - I think this is enough to support automating it, for the moment at least.
  • There are probably more things that could be automated as far as generation goes, but the above list is a (very) good start.
  • For anything that's not defined above, examples and patterns from the existing code-base of @angular-react/fabric can be used as reference.
@bengry bengry added help wanted Extra attention is needed pinned labels Feb 17, 2019
@bengry
Copy link
Contributor Author

bengry commented Feb 18, 2019 via email

@eswarpr
Copy link
Contributor

eswarpr commented Feb 19, 2019

Sorry, no idea what happened to my comment. Guess I accidentally deleted it. I am interested in trying this out but need to have a go at the Typescript compiler bit first

@eswarpr
Copy link
Contributor

eswarpr commented Feb 28, 2019

@bengry - So, after a bit of play around with ts-morph (which by the way is brilliant!) I think we need to put together some blue prints as to the input for the schematic that will help us identify which component file and prop type to process. At a high level, we have the following options:

  1. Accept the component name - for e.g. TextField, find the component from .d.ts in the "lib" folder of "office-ui-fabric-react" folder, traverse through the base class to arrive at the input to React.Component<> base class, and identify ITextFieldProps as the prop type. Once identified, parse and generate the Fab component for it
  2. Accept the prop type - for e.g. ITextFieldProps - derive the potential file that might host it - for e.g. TextField.types.d.ts then parse and generate the Fab component for it.

Looking at the options:

(1) is easier for the end user, since all they need to know is which component we need to generate. Harder for us, since we will need to walk the inheritance tree to find the prop type

(2) is easier for us (maybe) and harder for the end user, since they will need to tell us the prop type to use by browsing the component docs in the MS site.

I like (1) for obvious reasons. Do you have any other thoughts?

@bengry
Copy link
Contributor Author

bengry commented Mar 1, 2019

I agree that (1) is probably better, especially long-term. It introduces a minor technical challenge of getting the type of props, but if needed - we could extract more from it, without breaking the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed pinned
Projects
None yet
Development

No branches or pull requests

2 participants