mvcoconut / coconut.data Goto Github PK
View Code? Open in Web Editor NEWObservable Data Layer.
License: The Unlicense
Observable Data Layer.
License: The Unlicense
ProductData.hx:6: characters 12-65 : Error#500: Type name ProductResponse is already defined in this module @ #pos((unknown))
Like this, the typing error is reported in the model. But obviously it should be somewhere else.
Because the reported place is not defining any types, opposing to what the error says.
Guards are a currently undocumented feature, that work roughly like so:
class Example implements Model [
@:guard(Math.max(0, Math.min(1, next))
@:editable var volume:Float = 3;
}
The guard is called on every update of an editable or observable property, with prev
being the previous and next
being the next value. However it's not called upon construction. In this particular case having an abstract over float that does the clamping would be more elegant. Perhaps guards should simply be removed again.
Also, for Promised
, Outcome
, Option
(and combinations) compare the inner data via ==
.
something like this seems to compile:
@:loaded var profile:UserProfile = loadUser();
// ...
function loadUser():Promise<SomethingElse>;
I get a compile error when having something like this in a Model
(code just written out of the top of my head, sorry):
class MyModel implements Model {
@:loaded var somethingAmazing:Int = {
if (incredibleProperty == 0) calculatePlanToConquerWorld($last);
else if (incredibleProperty == 1) haveBreakfastBeforeConqueringTheWorld($last);
else conquerWorld();
};
@:editable private var incredibleProperty:Int = -1;
function calculatePlanToConquerWorld(whoKnows:Int) return Future.sync(1);
function haveBreakfastBeforeConqueringTheWorld(whoKnows:Int) return Future.sync(2);
}
It seems both $last
s are replaced by the same variable that is generated in the same scope as whichever is processed first (assumption based just in the error message and that having a top level $last
or single inner scope $last
works).
Please do not create toString()
method if model already has one.
Here is the minimal example that should be able to reproduce the issue. Note that 0.7.0 runs fine, problem occurs only in 0.8.1:
static public function main(){
new Minimal({list: []});
}
class Minimal implements coconut.data.Model {
@:constant var list:tink.pure.List<String>;
@:constant var child:MinimalChild = new MinimalChild({list:list});
}
class MinimalChild implements coconut.data.Model {
@:external var list:tink.pure.List<String>;
}
Updating both editables and observables from the same transition is a bit awkward. Allowing to put editable fields into the patch would help remedy that, but it would be a potentially breaking change.
Should help to speed up auto completion.
The following code causes a stack overflow:
import coconut.data.*;
class Main {
static function main() {
new Data({e:None});
}
}
class Data implements Model {
@:constant var e:MyEnum;
}
enum MyEnum {
None;
Some(e:MyEnum);
}
I think coconut could benefit from it's own extended version of tink_lang's @:forward
Limitations of using @:forward now:
@:observable
), setters will be generated (on the other hand it can be argued that the VOs should be properly defined as immutable)The following used to work:
class Main extends coconut.ui.View {
@:attr var f:Float = 2;
static function main() {}
function render() '<div/>';
}
but now it gives:
src/Main.hx:4: characters 23-24 : Int should be Null<coconut.data.Value<Float>>
src/Main.hx:4: characters 23-24 : For optional function argument 'defaultData'
In particular, start using final
wherever appropriate.
class Main {
public static function main() {}
}
class MyModel implements coconut.data.Model {
@:constant var color:Hsv;
}
abstract Hsv(Base) {}
@:pure
abstract Base(Array<Float>) {}
error: Hsv is not observable, because Array<Float> is not observable, because Array<Float> is not observable because the field "length" is mutable
Moving @:pure
to Hsv
will work though.
I am trying to write a Router while I found I need some sort of intializers/deinitializers, more or less equivalent to react's componentDidMount
/componentWillUnmount
.
For example, the RouterViewContainer should start to listen on the browsers history change when it is mounted, and unlisten when it is unmounted.
Now I am using a ugly hack:
class Roles implements Model {
@:observable var date:Date = @byDefault Date.now();
@:loaded var all:List<RoleResponse> = {date; Remote.fetchData();}
@:transition
function add(name:String) {
return Remote.addItem()
.next(function(_) return {date: Date.now()});
}
}
hi,
with this example that i have created https://github.com/francescoagati/coconut-data-error with haxe 4 rc2 i get this error ocaml
Typing tink.core.SignalTrigger.new
Typing tink.core.SignalTrigger.asSignal
Typing tink.core.Signal.Signal_Impl.trigger
Typing Store.update
Calling macro tink.macro.Types.resolveDirectType (C:\HaxeToolkit\haxe\lib\tink_macro/git/src/tink/macro/Types.hx:233)
Exiting macro tink.macro.Types.resolveDirectType
File "_build/src/macro/eval/evalContext.ml", line 342, characters 2-8: Assertion failed
How to use Array and Map inside Model?
@:editable var aviableLanguages:Array<String> = [];
this code gives me error that its not Observable, right now silenced it with @:skipCheck
, but don't feel that is best option.
Thank you
This is causing some loops in my app
Not sure why interface is rejected while structure is ok
interface MyInterface {
function myFunc():Void;
}
typedef MyTypedef = {
function myFunc():Void;
}
class Data implements Model {
@:constant var myTypedef:MyTypedef; // ok
@:constant var myInterface:MyInterface; // fail
}
It should be possible to detect when none of a model's observable/editable properties are in use and so that any underlying subscriptions (to a websocket or something) can be cleaned up.
coconut.data/src/coconut/data/macros/Models.hx
Lines 44 to 55 in 786a24b
This should make it easier to create custom structures.
@:history
A way this could work would be:
class Model {
@:constant var foo:Foo;
@:constant var bar:Bar;
public function new(arg1:T1, arg2:T2) {
// pre-construct
this = { foo: ..., bar: ... };
// post-construct
}
}
//Becomes:
class Model {
@:constant var foo:Foo;
@:constant var bar:Bar;
public function new(arg1:T1, arg2:T2) {
var initial = __cocoInit(argType);
// the usual initialization code
// post-construct
}
static function __cocoInit(arg1:T1, arg2:T2):{ foo:Foo, bar:Bar } {
// pre-construct
return { foo: ..., bar: ... };
}
}
This way it'll still be impossible to mess with the model while it's not yet initialized.
It would be easier to navigate when they are separated from the "core" types.
This compiles (because of a weird unification rule for {}
):
class Example implements Model {
@:editable var foo:Int = 0;
@:editable var bar:Int = 0;
}
new Example({
foo: 12,
bar: 13,
});
But it certainly doesn't do what's expected. The type of initial should probably be changed to Noise
or something else that will cause a compiler error.
I suppose @byDefault
should be allowed. So that if the field is omitted in the constructor it will behave like a @:constant
with the default value.
Consider having the following:
@:forward
abstract LanguageString(String) from String to String {}
typedef DialogData = {
final header:Value<LanguageString>;
}
//in hxx
@:attr var data:DialogData;
function render() <Text>${data.header}</Text>;
This will give compilation error:
Array<coconut.data.Value<LanguageString>> should be Null<react.ReactFragment>
unless provided with type hint like so <Text>${(item.header:String)}</Text>
.
This seem to be a regression as this was working with older versions.
Just like @:external
but backed by a State
and exposing the write access.
I forgot to change @:editable
to @:observable
when refactoring a coconut model to use a transition function:
@:editable var balance:Float = 0;
@:transition function setBalance(value:Float) return {balance: value};
The code compiles and doesn't cause run-time errors either, it just doesn't update the balance
property. It would be nice if mistakes like this would be caught, preferably at compile-time.
We need proper testing for the validation logic:
Here is one, for 3922226
package;
class Main implements coconut.data.Model {
@:constant var data:Data;
static function main() {}
}
abstract Data(VarChar<255>) {}
typedef VarChar<@:const P> = String;
Updates just don't seem to propagate.
Problem is that on rc3 Value was created out of T automagically like so
var a:Value<Int>;
a = 42;
and since rc5 this cast gives me compilation error so I have to create it basically from State:
var a:Value<Int>;
a = new State(23);
Is this expected?
Subject says it all I guess.
import coconut.data.*;
import haxe.Timer.delay;
using tink.CoreApi;
using tink.state.Promised;
class Main {
static function main() {
var data = new Data();
data.observables.details.bind(function(o:tink.state.Promised<Details>) {
switch o {
case Loading:
case Done(details):
delay(function() {
trace('update');
details.list.first().orNull().value += 1;
}, 1000);
case Failed(e):
}
});
js.Browser.document.body.appendChild(new View({value: data.details.map(function(details) return details.list.first().orNull().value)}).toElement());
}
}
class View extends coconut.ui.View<{value:Promised<Int>}> {
function render() '
<div>
<switch ${value}>
<case ${Loading}>
Loading
<case ${Done(value)}>
${Std.string(value)}
<case ${_}>
</switch>
</div>
';
}
class Data implements Model {
@:loaded var details:Details = Future.async(function(cb) delay(cb.bind(new Details()), 1000));
}
class Details implements Model {
@:constant var list:List<Value> = @byDefault List.fromArray([new Value()]);
}
class Value implements Model {
@:editable var value:Int = @byDefault 0;
}
Can't reduce yet...
Perhaps only with switch statements though.
The readme talks about var observable(default, never)
while it actually is var observables(default, never)
Yes I am back.
Most likely this is needed for some custom init, obviously.
I have been doing something like this many times:
https://github.com/kevinresol/coconut.router/blob/f5c324f/src/coconut/router/RouteData.hx#L14-L15
This is mostly for @:external. While it is named external, it doesn't need to be external (in terms of OOP classes). They are merely non-coconut-managed observables. In the above example, url is @:external and basically it observes window.location.href
. And since I need to set up the required listeners, I need an custom constructor like this:
// wished
function new() {
var state = new State(location.href);
setupListenerToLocationhref(state);
super({url: state.observe());
}
// currently
public static function create() {
var state = new State(location.href);
setupListenerToLocationhref(state);
return new Data({url: state.observe());
}
In other words, I am merely trying to prepare the required init inline, and ultimately I am going to pass the init object to super()
.
I worked around it with a static function. But the problem is that I need to make sure I use it instead of the constructor, otherwise I am doomed.
It would be great with an example or two how to best deal with model persistence, at least from and to json data.
In many cases it'd be a better choice than @:observable
.
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.