CARVIEW |
Navigation Menu
-
Notifications
You must be signed in to change notification settings - Fork 38
Support Injector instances in Registry and add inject decorator #668
Conversation
src/Injector.ts
Outdated
private _context: T; | ||
|
||
constructor(context: T = <T> {}) { | ||
constructor(context: any) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the reason/motivation for the context being untyped? Not challenging, just wondering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a challenge with the typing, I'll try it again and let you know (can't remember off the top of my head).
Also wasn't sure what the benefit really was, seen as it's injected at run time there's it didn't really give much to the consumer. The important typing is really on the getProperties
function that gets passed the context, which the user can type as needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was imagining the challenge it seems, updated to accept a generic type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do get the point about the value of it...
@@ -29,31 +30,55 @@ export interface RegistryEvents extends BaseEventedEvents { | |||
/** | |||
* Widget Registry Interface | |||
*/ | |||
export interface Registry { | |||
export interface RegistryInterface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have traditionally not mentioned Interface
in our interfaces. Why the change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did it have something to do with name merging? Could this be a use case for an abstract class and having an AbstractRegistry
as an export?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason was, that without a different name for the interface TS didn't actually error if the class didn't implement it! We've used a suffix of Interface
in some of the interfaces exported from interfaces.d.ts
which was the motivation.
I don't think Abstract
works because the registry isn't actually abstract?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Thanks.
src/decorators/inject.ts
Outdated
getProperties: GetProperties; | ||
} | ||
|
||
export function inject({ name, getProperties }: InjectConfig) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some basic JSDoc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooops yup!
src/Registry.ts
Outdated
public getInjector<T extends Injector>(label: RegistryLabel): T | null { | ||
if (!this.hasInjector(label)) { | ||
if (this.has(label)) { | ||
console.warn(`Unable to find injector '${label.toString()}', did you mean to get a widget?`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm not convinced we need these warns, because the api is separate and returns discreet types (that extend Injector), the user thus shouldn't be able to get this wrong at design time.
src/decorators/inject.ts
Outdated
export function inject({ name, getProperties }: InjectConfig) { | ||
return handleDecorator((target, propertyKey) => { | ||
beforeProperties(function(this: WidgetBase, properties: any) { | ||
const context = this.registries.getInjector(name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be called injector
, over context
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup good shout
src/decorators/inject.ts
Outdated
* used to map the injected properties. | ||
*/ | ||
export interface GetProperties<T = any> { | ||
(context: any, properties: T): T; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this context
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the context
from the Injector
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is a context
? can we get a better name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am receptive to better names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't participate in suggesting a name without knowing what it is 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want it to be payload
, I don't have any strong attachment to context
or objections to payload
- they both work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the reason i don't like context
is the baggage that comes from react with it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup I understand that. Let me update that for you - I think both are okay and if using context
could lead to confusing that is it enough reason to change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value
? Since you are injecting a value of some sort that can be any
. Do we actually expect it to be any
or is it an object
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aye it can be a any
, just as the payload
of an Injector
can be.
return class extends WidgetBase<any> { | ||
@inject({ name, getProperties }) | ||
class WidgetContainer extends WidgetBase<Partial<W['properties']>> { | ||
public __setProperties__(properties: Partial<W['properties']>): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have we thought how we can better support this in the future? this is the equivalent of shouldComponentUpdate
set to true
in react?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have thought about it, shall raise an enhancement issue - for now this is the only way I could support it.
src/WidgetBase.ts
Outdated
@@ -706,7 +706,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E | |||
let child: WidgetBaseInterface<WidgetProperties>; | |||
|
|||
if (!isWidgetBaseConstructor(widgetConstructor)) { | |||
const item = this.getRegistries().get(widgetConstructor); | |||
const item = this.registries.get(widgetConstructor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this the only place the registries
are accessed? just noticed that we've renamed it back now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think everywhere else actually accesses the private (_registries
) in WidgetBase
, I'll update this to do that.
Type: feature
The following has been addressed in the PR:
Description:
Adds
inject
decorator to support side loading properties from a Injector instance registered in theRegistry
.Includes:
defineInjector
,getInjector
,hasInjector
)inject
decorator that registers a function that will be called with the injector instances context and the widget properties in thebeforeProperties
phase.Container
&Themeable
to use mixin pattern for addinginject
decoratorBaseInjector
that extendsWidgetBase
theInjector
HOCWidgetBase.getRegistries()
toWidgetBase.registries
Resolves #648