Skip to content

Conversation

@MarcOne68
Copy link

I defined the class RenderOverride.
You can create an instance of this class passing a IRenderFunction<...> and set the Render* property of a component with that instance.

@msftclas
Copy link

msftclas commented Jan 27, 2019

CLA assistant check
All CLA requirements met.

bengry
bengry previously approved these changes Jan 27, 2019
Copy link
Contributor

@bengry bengry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MarcOne68 Can you give an example use-case for this change + the code in the app that would use it? Why would you prefer to write your own function rather than return one of the already-available options (TemplateRef/ComponentRef/function returning an HTML element).

}

if (input instanceof RenderOverride) {
return undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not return input.renderer?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How I wrote in Issue #72, these changes help me to set the styles
This is the code example:

private overrideRenderRow(props: IDetailsRowProps, defaultRender: (props: IDetailsRowProps) => JSX.Element): JSX.Element {
  props.styles = MY_STYLES;
  return defaultRender(props);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable - you want to expose the native JSX to Angular-land then. This should be fine for simple cases, since JSX in Angular is something I’d like to avoid (although possible of course).

However, I suggest we change the API, to avoid the boilerplate of creating a class (which would really only have one instance), if possible.
I want to think about an API further, and see if we can somehow avoid exposing JSX to the final user (i.e. the developer using @angular-react/fabric) - perhaps allowing to pass a function that accepts TProps and returns TProps, which will then be fed to the defaultRenderer that office-ui-fabric-react exposes. If you have an idea for an API - I’m open for suggestions, and how it would work.

@bengry bengry dismissed their stale review January 27, 2019 12:12

clicked approve by mistake

import { toObject } from '../utils/object/to-object';
import { afterRenderFinished } from '../utils/render/render-delay';
import { unreachable } from '../utils/types/unreachable';
import { IRenderFunction } from 'office-ui-fabric-react';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don’t import stuff from office-ui-fabric-react inside the @angular-react/core package - we want to keep it library-agnostic.

A more generic type is needed here instead therefore.

@bengry bengry self-assigned this Jan 28, 2019
Copy link
Contributor

@bengry bengry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comments

export class RenderOverride<TContext extends object> {
constructor(public renderer: IRenderFunction<TContext>) { }
export interface DefaultRenderOptions<TContext extends object> {
readonly getProps: (props?: TContext) => TContext;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe rename to defaultProps, to make it clearer.


// Call the function again with the created ComponentRef<TContext>
return this.createInputJsxRenderer(componentRef, additionalProps);
if ('componentType' in input) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please replace this with a user defined type guard, this function does too much at the moment (it was bearable so far since it only had to deal with one object, but in hindsight it should've extracted the "is this a RenderComponentOptions" to a user defined type guard.

Also, you want to check with hasOwnProperty, since it doesn't look up the prototype chain.

// Call the function again with the created ComponentRef<TContext>
return this.createInputJsxRenderer(componentRef, additionalProps);
} else {
return undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this undefined in the DefaultRenderOptions case?

Copy link
Contributor

@bengry bengry Jan 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the technical reason of why needing to handle this case is here - but why is returning undefined specifically? Shouldn't there be a render function call here, or rather, a function that creates a render function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only because unreachable(input) throw an error during the compilation.
The execution never reach that line of code because the method createRenderPropHandler executes the cases RenderPropOptions and RenderPropContext.

): (props?: TProps, defaultRender?: JsxRenderFunc<TProps>) => JSX.Element | null {
if (renderInputValue instanceof RenderOverride) {
return renderInputValue.renderer;
if ((typeof renderInputValue === 'object') && ('getProps' in renderInputValue)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a user-defined type guard here, as mentioned in the other comment. Making one will also make sure you can re-use the logic of it in multiple places.


export class RenderOverride<TContext extends object> {
constructor(public renderer: IRenderFunction<TContext>) { }
export interface DefaultRenderOptions<TContext extends object> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking out load here - the DefaultRenderOptions doesn't convey the message that it allows mutating the props. If you have suggestions for a better/other name - I'm open for suggestions, but if not - please add a JDoc comment explaining what the purpose of this object is.

@Output() readonly onChange = new EventEmitter<{ event: Event; newValue?: string }>();
@Output() readonly onBeforeChange = new EventEmitter<{ newValue: any }>();
@Output() readonly onNotifyValidationResult = new EventEmitter<{ errorMessage: string; value: string | undefined }>();
@Output() readonly onBlur = new EventEmitter<{ event: Event }>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move these changes to a separate PR. It makes it easier to maintain and create the changelog (this part of the PR looks fine as it is, so if you move it it can get it as-is)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll try to do it but.... I don't know so well GIT :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically create a new branch from master and make the same changes there (or you can cherry-pick the commit using git cherry-pick 95e1991 when you're on the new branch.
Then create a new PR from it.

@bengry
Copy link
Contributor

bengry commented Mar 2, 2019

@MarcOne68 This is a good PR (or two, as I mentioned in another comment).
Is this something you're still working on and would like to merge? It's been over a month since the last change here.

@bengry
Copy link
Contributor

bengry commented Mar 25, 2019

Implemented as part of #92 and #99.

@bengry bengry closed this Mar 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants