-
Notifications
You must be signed in to change notification settings - Fork 37
Add evented Node handler to meta #666
Conversation
| this._diffPropertyFunctionMap = new Map<string, string>(); | ||
| this._bindFunctionPropertyMap = new WeakMap<(...args: any[]) => any, { boundFunc: (...args: any[]) => any, scope: any }>(); | ||
| this._registries = new RegistryHandler(); | ||
| this._nodeHandler = new NodeHandler(); |
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 should own this
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.
done
agubler
left a comment
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.
a few comments
src/NodeHandler.ts
Outdated
| Widget = 'Widget' | ||
| } | ||
|
|
||
| export default class NodeHandler extends Evented { |
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.
Can we make this a named export and export default below (a pattern for most widget-core modules)
src/NodeHandler.ts
Outdated
| import { VNodeProperties } from '@dojo/interfaces/vdom'; | ||
| import Map from '@dojo/shim/Map'; | ||
|
|
||
| export enum 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.
Can we have some documentation on these (and the rest of the module?), is type descriptive enough?
src/NodeHandler.ts
Outdated
| } | ||
|
|
||
| public addRoot(element: Element, properties: VNodeProperties) { | ||
| this.add(element, properties); |
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.
Do you need the key check for adding the root too?
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.
good catch
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.
can we add a failing test for this if it needs the guard 😄
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.
way ahead of you 😉
src/WidgetBase.ts
Outdated
|
|
||
| private _nodeHandler: NodeHandler; | ||
|
|
||
| private _projectorMountEvent: 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.
is this really 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.
unlikely
| this._diffPropertyFunctionMap = new Map<string, string>(); | ||
| this._bindFunctionPropertyMap = new WeakMap<(...args: any[]) => any, { boundFunc: (...args: any[]) => any, scope: any }>(); | ||
| this._registries = new RegistryHandler(); | ||
| this._nodeHandler = new NodeHandler(); |
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.
Need to own this
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.
done
src/WidgetBase.ts
Outdated
| node.properties = node.properties || {}; | ||
| if (isHNode(node)) { | ||
| if (node.properties.key) { | ||
| if (rootNodes.indexOf(node) < 0 && node.properties.key) { |
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.
why not === -1?
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.
looks a bit confusing like that to me
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.
ok
src/interfaces.d.ts
Outdated
| */ | ||
| export interface WidgetMetaRequiredNodeCallback { | ||
| (node: HTMLElement): void; | ||
| nodeHandler: 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.
type? might need to create an interface in here for NodeHandler
src/meta/Base.ts
Outdated
| private _invalidating: number; | ||
| private _requiredNodes: Map<string, ([ WidgetMetaBase, WidgetMetaRequiredNodeCallback ])[]>; | ||
| protected nodes: Map<string, HTMLElement>; | ||
| protected nodeHandler: 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.
Type please
src/mixins/Projector.ts
Outdated
| return this._projection.domNode.outerHTML; | ||
| } | ||
|
|
||
| _afterRootCreateCallback(element: Element, |
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.
formatting a bit weird here (and the other functions)
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.
done
| import NodeHandler, { Type } from '../../../src/NodeHandler'; | ||
|
|
||
| let rAF: any; | ||
| const defaultDimensions = { |
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.
Don't we export these from dimensions?
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.
no, i did add that earlier but removed again, makes sense
src/NodeHandler.ts
Outdated
| this.emit({ type: key }); | ||
| } | ||
|
|
||
| public addRoot(element: HTMLElement, properties: VNodeProperties) { |
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 know this is a bit picky, but you could have a single function that does this, and three specific functions that pass their type. Like:
public add(element: HTMLElement, properties: VNodeProperties) {
if (properties.key) {
this.add(element, properties);
}
this.emit({ type: properties.key });
}
public addRoot(element: HTMLElement, properties: VNodeProperties) {
this._add(element, properties, Type.Widget);
}
public addProjector(element: HTMLElement, properties: VNodeProperties) {
this._add(element, properties, Type.Projector);
}
private _add(element: HTMLElement, properties: VNodeProperties = {}, type: Type) {
if (properties.key) {
this.add(element, properties);
}
this.emit({ 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.
fair. but doesn't quite work, as a root or a projector may have a key and thus needs to be emited via it's key as well as via it's 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.
Isn't that logically actually same?
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.
disclosure, I updated the code :)
src/WidgetBase.ts
Outdated
| this.onElementUpdated(element, String(properties.key)); | ||
| } | ||
|
|
||
| _addElementToNodeHandler(element: Element, projectionOptions: ProjectionOptions, properties: VNodeProperties) { |
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 private? let's add the visibility modifier.
src/WidgetBase.ts
Outdated
| _addElementToNodeHandler(element: Element, projectionOptions: ProjectionOptions, properties: VNodeProperties) { | ||
| this._currentRootNode += 1; | ||
|
|
||
| if (!this._projectorAttachEvent) { |
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.
minor nit: I believe if (this._projectorAttachEvent === undefined) { is more performant and also personally I find it clearer.
src/WidgetBase.ts
Outdated
| this._currentRootNode += 1; | ||
|
|
||
| if (!this._projectorAttachEvent) { | ||
| this._projectorAttachEvent = projectionOptions.nodeEvent.on('attached', |
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 should own this._projectorAttachEvent also
src/WidgetBase.ts
Outdated
| } | ||
|
|
||
| public __render__(): VirtualDomNode | VirtualDomNode[] { | ||
| this._nodeHandler.clear(); |
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 correct place for this? so it clears regardless of whether the widget was invalidated.... I don't think that this is the equivalent to when it was executed in the @beforeRender...
src/interfaces.d.ts
Outdated
| new (properties: WidgetMetaProperties): T; | ||
| } | ||
|
|
||
| export interface NodeHandler extends Evented { |
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 tend to have doc on exported interfaces (we also tend to suffix with Interface)
src/meta/Dimensions.ts
Outdated
| } | ||
|
|
||
| const defaultDimensions = { | ||
| export const defaultDimensions = { |
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.
thinking about this, doesn't this mean that something external could mess with the defaults?
src/meta/Dimensions.ts
Outdated
| constructor(properties: WidgetMetaProperties) { | ||
| super(properties); | ||
|
|
||
| this.nodeHandler.on(NodeEventType.Projector, () => { |
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 this is going to put us in a loop no?
| private _addElementToNodeHandler(element: HTMLElement, projectionOptions: ProjectionOptions, properties: VNodeProperties) { | ||
| this._currentRootNode += 1; | ||
|
|
||
| if (this._projectorAttachEvent === undefined) { |
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 isn't really attached or mount (which it previously was), and more after dom update no?
| public __render__(): VirtualDomNode | VirtualDomNode[] { | ||
| this._renderState = WidgetRenderState.RENDER; | ||
| if (this._dirty === true || this._cachedVNode === undefined) { | ||
| this._dirty = false; |
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 still think that this is in the wrong place, it will clear the map before running the renders and therefore always return back the default dimensions! This is were integration tests for using the meta with WidgetBase come in handy.
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.
moved down
| Widget = 'Widget' | ||
| } | ||
|
|
||
| export class NodeHandler extends Evented implements NodeHandlerInterface { |
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 are two things I've been struggling with using meta that this could perhaps help with. The first is doing a reverse lookup and the second is knowing what the currently rendered keys are. I need the reverse lookup for intersection meta where I have a single observer that receives multiple events. I don't have a good use case for knowing all the keys, but I could see it being potentially helpful/related to whatever we'd have to do for a reverse lookup.
agubler
left a comment
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.
couple more nits
src/NodeHandler.ts
Outdated
| return this._nodeMap.has(key); | ||
| } | ||
|
|
||
| public add(element: HTMLElement, properties: VNodeProperties) { |
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.
nit: can you add return type of : void please?
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.
In other places through the PR also?
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.
Maybe it's okay because it is defined on the interface, I don't know what the standards are around this. Can't hurt to add them I guess.
| throw new Error(`Required node ${key} not found`); | ||
| } | ||
|
|
||
| const handle = this.nodeHandler.on(key, () => { |
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.
maybe should own this
src/mixins/Projector.ts
Outdated
| return this._projection.domNode.outerHTML; | ||
| } | ||
|
|
||
| protected afterRootCreateCallback(element: HTMLElement, |
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 this formatting is really funky :) is it different from the formatting in widget base?
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 you're really funky
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.
Formatting is the same as in widgetbase
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.
it's not the same, it is like this in widget base
protected afterRootCreateCallback(
element: HTMLElement,
projectionOptions: ProjectionOptions,
vnodeSelector: string,
properties: VNodeProperties
): void {
// ... stuff
}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.
notice the first param is on the next line?
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.
my apologies, have fixed
src/meta/Base.ts
Outdated
| if (!callback) { | ||
| this.invalidate(); | ||
| if (!node) { | ||
| if (this._requestedNodeKeys.has(key)) { |
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.
Won't this throw an error if it's called twice? And is the assumption that .has would always be used to check to see if a node exists and never .getNode? Throwing an error as a side-effect of a getter could be unexpected.
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.
Good catch re the error @pottedmeat. I'll remove the error and only add to the requested keys if it does not already exist in there. Thanks
src/WidgetBase.ts
Outdated
| } | ||
|
|
||
| protected afterRootUpdateCallback( | ||
| private afterRootUpdateCallback( |
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.
needs the _ prefix
src/WidgetBase.ts
Outdated
| } | ||
|
|
||
| protected afterRootCreateCallback( | ||
| private afterRootCreateCallback( |
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.
needs the _ prefix
src/WidgetBase.ts
Outdated
| currentRootNode += 1; | ||
| currentRootNodeMap.set(this, currentRootNode); | ||
| const isLastRootNode = (currentRootNode === numRootNodes); | ||
| this._currentRootNode += 1; |
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.
why not this._currentRootNode++
Type: feature
The following has been addressed in the PR:
Description:
nodehandlerto metaResolves #662