fponticelli / doom Goto Github PK
View Code? Open in Web Editor NEWVirtual Dom Library for Haxe
License: MIT License
Virtual Dom Library for Haxe
License: MIT License
Hello, I've debugged a bit the issue I had here https://groups.google.com/forum/#!topic/haxelang/5bViIOBmKkQ and I think I've found the problem. So the component structure is this one:
- header
- div.row
- ...
- div.loader-active
After it is mounted the DOM changes to this:
- header
- div.menu-button (added by the css/js framework)
- div.row
- ...
- div.loader-active
And, here is the problem, when the component goes to render again it will override the div.row
with div.loader-inactive
so:
- header
- div.menu-button
- div.loader-inactive
- ...
- div.loader-active
I've checked the patches that get applied to the node and it shows that it will apply a PatchChild(1, oldLoader, newLoader)
PatchChild(0,
MigrateComponentToComponent(HeaderComponent(<header class="demo-header mdl-layout__...s--indeterminate is-active"/></header>),HeaderComponent(<header class="demo-header mdl-layout__...l-progress--indeterminate "/></header>))
PatchChild(1,
MigrateComponentToComponent(LoadingComponent(<div id="loading-element" class="mdl-pr...l-progress--indeterminate is-active"/>),LoadingComponent(<div id="loading-element" class="mdl-pr...ogress mdl-progress--indeterminate "/>))
SetAttribute(class,StringAttribute(mdl-progress mdl-js-progress mdl-progress--indeterminate ))))
Notice the second PatchChild
, it should be 2 because the new added div.menu-button
by the css/js framework.
This issue is to try to figure out how an AutoComponent
macro thing could work in doom. I have some code in a branch to start this, so I can work on it and do a PR.
There would be an doom.AutoComponent
interface with an @:autoBuild
metadata to transform the implementing class, add the State and Api typedefs, generate getters for state/api properties, setup defaults, etc.
The idea is to turn something like this:
enum MyComponentStyle {
Default;
Primary;
Other;
}
// could have @:noChildren metadata on the class to indicate that the component can't have children?
class MyComponent implements AutoComponent {
@:state
public var style : MyComponentStyle;
@:state
@:optional
@:default(123)
public var size : Int;
@:api
public var click : Void -> Void; // should this be an empty function rather than var? - I made it a var, so a property accessor could return api.click
@:api
@:optional
public var hover : Void -> Void; // should this be an empty function?
// user defined render function
public override function render() : Node {
var styleClass = switch style { /* some code */ };
var sizeClass = /* some code */;
return div([
'class' => 'my-component $styleClass $sizeClass',
'click' => click,
'hover' => hover
], children);
}
}
into this (via macros):
enum MyComponentStyle {
Default;
Primary;
Other;
}
typedef MyComponentApi = {
public function click() : Void;
public function hover() : Void;
}
typedef MyComponentState = {
style : MyComponentStyle,
size : Int
}
class MyComponent extends Component<MyComponentApi, MyComponentState> {
public var style(get, null) : MyComponentStyle;
public var size(get, null) : Int;
public var click(get, null) : Void -> Void;
public var hover(get, null) : Void -> Void;
// don't generate ctor - use super ctor
// static convenience constructor function
// should this call `render` on the component and return Node?
public static function create(click : Void -> Void, ?optApi : { ?hover: Void -> Void }, style : MyComponentStyle, ?optState : { ?size : Int }, ?children : Nodes) : MyComponent {
if (optApi == null) optApi = {};
if (optApi.hover == null) optApi.hover = function() {}; // no-op - not sure how best to deal with this
if (optState == null) optState = {};
if (optState.size == null) optState.size = 123; // from @:default metadata
return new MyComponent({
click: click,
hover: optApi.hover
}, {
style: style,
size: optState.size
}, children);
}
public override function render() : Node {
// unchanged from above
}
public function get_style() : MyComponentStyle {
return state.style;
}
public function get_size() : Int {
return state.size;
}
public function get_click() : Void -> Void {
return api.click;
}
public function get_hover() : Void -> Void {
return api.hover;
}
// all other functions from above preserved here
}
Line 161 in 463c52a
If src == dst, then there is a leak as the function proxy call stack grows with each migrate.
would be nice to see them :)
Does it work to change public var nodeToComponent(default, null) : Map<DOMNode, Component<Dynamic>>;
to Map<DOMNode, Array<Component<Dynamic>>>
. This might provide an alternate solution to the VNode vs VChild issue?
Is this line missing a @:from
? https://github.com/fponticelli/doom/blob/master/src/doom/core/VChildren.hx#L17
haxe build.hxml
phantom.js: test errors
doom.html.TestComponent
testComponentIsRemovedFromDom: FAILURE FF
line: 194, expected 2 elements but they are 0
line: 200, expected 0 elements but they are 3
testComponentReplacedByElement: FAILURE .FF
line: 155, expected 2 elements but they are 0
line: 161, expected 0 elements but they are 3
Error: Command failed with error 1
I found out that an event listener is not removed in my case, i use bind to add a click listener, do you know if this is a known issue?
public static function render (state:State, api:Api) {
return div(
state.active ? button( "Enable") : button(["click" => api.removeState.bind()], "Disable");
);
}
Create an initialization macro function that would be invoked like: haxe --macro Doom.cssPath("../some/path/master.css")
. This function should save the file path in a static variable for future macro use.
Each Component
can then define a @:style("comp.css")
meta (at the class level) to specify the path to a .css file for the component.
The AutoComponentBuild macro should load the .css file for each component (if specified), and append the contents in the master file specified by the Doom.cssPath init macro. This way, each component in the app can have a style sheet that is automatically combined with all other components. The @:style
macro might need a way to specify or generate a unique class name for the component.
Not sure if this will work...
E.g. mithril has a syntax like m("div#my-id.my-class.another-class[placeholder=test][type=something]"
Maybe in Doom.hx
, we could have a method like this:
The first arg would be a selector string that is parsed into attributes. You can still provide the other usual map of attributes (which would be merged with the selector attributes), and children/child.
// D for "Doom", like m for mithril ???
inline public static function D(selector : String, ?attributes : Map<String, AttributeValue>, ?children : Array<Node>, ?child : Node) {
var attrs = parseSelector(selector); // returns Map<String, AttributeValue>
attrs = attrs.merge(attributes); // merge map of attrs over the selector attrs?
// not sure how to get the element name from attrs?
return el(....);
}
Usage:
D("div#my-div.my-class.another-class[some-attr=some-value]", [ /* optional attrs */ ], [ /* optional children */ ]);
Parse the selector string format at compile time (for performance benefit and type-checking).
I can work on this at some point, or if you feel like doing it, free free.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.