Dart mixin with a polymer observable field possible? - dart

So lets say I have a mixin class defined like so:
abstract class TestMix
{
#observable bool loggedIn = false;
updateLogin(){
if (isLoggedIn()){
loggedIn = true;
}else{
loggedIn = false;
}
}
}
I'd want to mix in this behavior to a few polymer views, so I do:
#CustomTag('my-app')
class App extends PolymerElement with TestMix {
App.created() : super.created() {
this.updateLogin(); // #observable field 'loggedIn' is changed in the mixin
}
}
I get no binding joy. If I move the mixin fields/methods directly into the App class, then everything works fine and binding occurs.
Just want to confirm if this is possible or not? Can Dart reflect on mixin fields just like native fields? Or if there is a way to manually cause the binding pass to occur (would prefer not).

Yes you can. I have found this way works
abstract class TestMix implements Observable
{
bool _loggedIn = false;
#reflectable bool get loggedIn => _loggedIn;
#reflectable set loggedIn(val) {
_loggedIn = notifyPropertyChange(#loggedIn, _loggedIn, val);
}
updateLogin(){
if (isLoggedIn()){
loggedIn = true;
}else{
loggedIn = false;
}
}
isLoggedIn() => true;
}
Using
#observable
in the mixin causes real trouble where it keeps saying mixin needs to extend Object, even when you do. So I had to take a look at the docs in the source code and came across that suggestion in the above code, or something similar. Look in the observe package under observe/observe.dart. Though the trouble
#observable
caused in the mixin may just be a bug.
Oh and don't forget, to minimise the size of the generated code, as suggested by the docs, use
import 'package:observe/mirrors_used.dart';
when using things annotated with
#reflectable
Though I'm not totally sure Polymer apps need this import

Related

How do I set a property in a polymer-dart behavior mixin?

The following example is taken from the polymer-dart documentation on behaviors. It makes use of the method set in toggleHighlight. I don't understand how this is possible since set isn't defined anywhere.
#behavior
abstract class HighlightBehavior {
#Property(notify: true, observer: 'highlightChanged')
bool isHighlighted = false;
static created(instance) {
print('Highlighting for $instance enabled!');
}
#Listen('click')
toggleHighlight(_, __) {
set('isHighlighted', !isHighlighted);
},
#reflectable
highlightChanged(bool newValue, _) {
toggleClass('highlighted', newValue);
}
}
How do I set a polymer property in a behavior that triggers all the functionality that makes data binding work?
Should a behavior possibly implement PolymerBase to be able to use the set-method? A quick test reveals that set works when the behavior implements PolymerBase. But this is not how it is documented. May I induce some unwanted side-effects by implementing PolymerBase?
The HighlightBehavior is abstract, so real instances are obtained with inheritance. From the documentation
class MyElement extends PolymerElement with HighlightBehavior {
MyElement.created() : super.created();
}
The PolymerElement extends PolymerBase which supply the set method.

Dart Cross-Polymer Action Listerners

I have two dart polymer components defined: an input and a list
This looks a little something like this:
#CustomTag('input-button')
class Input extends PolymerElement {
#observable String value = '';
Input.created() : super.created();
void blah(Event e, var detail, Node target) {
someMethodCallToTheOtherObject(value);
}
}
and the other element:
#CustomTag('page-content')
class PageContent extends PolymerElement {
final List<String> values = stuff;
PageContent.created() : super.created();
someMethodCallListerningForEventInOtherObject(String value) {
values.add(value);
}
}
As demonstrated in the code, I'm trying to set up and ActionListerner so that when one method is "fired" in the first button object, it calls a method in the second object with given parameters.
I know this might be a little of the basic side, but I haven't see this concept really well documented anywhere. Any input you could give to point me in the right direction would be appreciated.
Thanks!
You can query for one element and add an event listener
(querySelector(' /deep/ page-content') as PageContent)
.someMethodCallListerningForEventInOtherObject(value);
as PageContent is not necessary but it enables autocompletion.
You also need to import the file that contains the PageContent class to make this work.
or you can use an element like core-signals or a number of other possible variants depending on how your elements are organized (see my comments to your question).

Implement an Observer pattern in Dart

I would like to implement an observer pattern in Dart but I'm not sure how to go about it.
Let's say I have a class:
class MyClass {
String observed_field;
}
Now, whenever I change the field, I'd like to print "observed_field changed" string into the console. Pretty simple to do with a custom setter:
class MyClass {
String _observed_field;
get observed_field => _observed_field;
set observed_field(v) {
_observed_field = v;
print("observed_field changed");
}
}
Now, of course, if I have not one, but many of those fields, I wouldn't want to create all those getters and setters. The obvious theoretical solution is to have them dynamically added to the class with something like this (not a working code, just an example of how I wish it looked):
class MyClass
String _observeable_field;
String _observeable_field_2;
observe(#observeable_field, #observeable_field_2);
end
Is it even possible? Additionally, it would be super awesome to not have those fields defined above the observe() call, but rather write something like:
observe(String: #_observeable_field, String: #_observeable_field_2);
So that those fields are declared automatically.
Here's a way to do it using the Observe package. The example is taken from code comments in that package (and adapted to your example above). Essentially, you annotate fields you want to be observable with the #observable annotation, and then listen for changes (which you trigger with the call to Observable.dirtyCheck();
First, add the observable package in your pubspec.yaml
dependencies:
observe: any
Then create a quick test program...
import 'package:observe/observe.dart';
class MyClass extends Object with Observable {
#observable String observedField = "Hello";
toString() => observedField.toString();
}
main() {
var obj = new MyClass();
// anonymous function that executes when there are changes
obj.changes.listen((records) {
print('Changes to $obj were: $records');
});
obj.observedField = "Hello World";
// No changes are delivered until we check for them
Observable.dirtyCheck();
print('done!');
}
This produces the following output:
Changes to Hello World were: [#<PropertyChangeRecord Symbol("observedField") from: Hello to: Hello World>]
done!
Update in response to comments...
Updating the example to omit the Observable.dirtyCheck() you can use a setter and notifyPropertyChanged, with the class instead mixing in ChangeNotifier
class MyClass2 extends Object with ChangeNotifier {
String _observedField = "Hello";
#reflectable get observedField => _observedField;
#reflectable set observedField(v) {
_observedField = notifyPropertyChange(#observedField, _observedField, v);
}
toString() => observedField;
}

What is the Dart "Expando" feature about, what does it do?

Have been seeing the term "Expando" used recently with Dart. Sounds interesting. The API did not provide much of a clue to me.
An example or two could be most helpful!
(Not sure if this is related, but I am most anxious for a way to add methods (getters) and/or variables to a class. Hoping this might be a key to solving this problem. (hint: I am using the Nosuchmethod method now and want to be able to return the value of the unfound method.))
Thanks in advance,
_swarmii
Just to clarify the difference between expando and maps: as reported in the groups, expando has weak references.
This means that a key can be garbage collected even if it's still present in the expando (as long as there are no other references to it).
For all other intents and purposes it's a map.
Expandos allow you to associate objects to other objects. One very useful example of this is an HTML DOM element, which cannot itself be sub-classed. Let's make a top-level expando to add some functionality to an element - in this case a Function signature given in the typedef statement:
typedef CustomFunction(int foo, String bar);
Expando<CustomFunction> domFunctionExpando = new Expando<CustomFunction>();
Now to use it:
main(){
// Assumes dart:html is imported
final myElement = new DivElement();
// Use the expando on our DOM element.
domFunctionExpando[myElement] = someFunc;
// Now that we've "attached" the function to our object,
// we can call it like so:
domFunctionExpando[myElement](42, 'expandos are cool');
}
void someFunc(int foo, String bar){
print('Hello. $foo $bar');
}
I played with it a little bit. Here's what I've got.
import 'dart:html';
const String cHidden = 'hidden';
class ExpandoElement {
static final Expando<ExpandoElement> expando =
new Expando<ExpandoElement>("ExpandoElement.expando");
final Element element;
const ExpandoElement._expand(this.element);
static Element expand(Element element) {
if (expando[element] == null)
expando[element] = new ExpandoElement._expand(element);
return element;
}
// bool get hidden => element.hidden; // commented out to test noSuchMethod()
void set hidden(bool hidden) {
if (element.hidden = hidden)
element.classes.add(cHidden);
else
element.classes.remove(cHidden);
}
noSuchMethod(InvocationMirror invocation) => invocation.invokeOn(element);
}
final Expando<ExpandoElement> x = ExpandoElement.expando;
Element xquery(String selector) => ExpandoElement.expand(query(selector));
final Element input = xquery('#input');
void main() {
input.classes.remove(cHidden);
assert(!input.classes.contains(cHidden));
input.hidden = true;
assert(x[input].hidden); // Dart Editor warning here, but it's still true
assert(!input.classes.contains(cHidden)); // no effect
input.hidden = false;
assert(!x[input].hidden); // same warning, but we'll get input.hidden via noSuchMethod()
assert(!input.classes.contains(cHidden));
x[input].hidden = true;
assert(input.hidden); // set by the setter of ExpandoElement.hidden
assert(input.classes.contains(cHidden)); // added by the setter
assert(x[input].hidden);
assert(x[input].classes.contains(cHidden)); // this is input.classes
x[input].hidden = false;
assert(!input.hidden); // set by the setter
assert(!input.classes.contains(cHidden)); // removed by the setter
assert(!x[input].hidden);
assert(!x[input].classes.contains(cHidden));
// confused?
assert(input is Element);
assert(x[input] is! Element); // is not
assert(x[input] is ExpandoElement);
assert(x is Expando<ExpandoElement>);
}

Does the Dart programming language have an equivalent to Javascript's "prototype"?

In Dart, is it possible for a function to have a prototype associated with it?
Example Javascript code:
doStuff.prototype.isDefined = true; //is there anything like Javascript's function prototypes in Dart?
function doStuff(){
console.log("The function doStuff was called!");
}
Is it possible to do the equivalent of this in Dart (i.e., create a list of properties for each function?)
Two things to address here:
First, Dart doesn't have prototypes or prototypal inheritance, and instead uses classical inheritance. Rather than a prototype, objects have a class, and instead of a prototype chain, objects have superclasses.
Second, for your specific case, I think we'd have to see more of what you need to do to figure out the idiomatic way to do it in Dart. It should soon be possible to emulate functions with objects so that you can invoke an object and still have state and other methods associated with it.
See this article for more: http://www.dartlang.org/articles/emulating-functions/
When that capability lands you'll be able to do this:
class DoStuff {
bool isDefined = true;
call() => print("The function doStuff was called!");
}
var doStuff = new DoStuff();
main() => doStuff();
Which works if you have a fixed set of metadata about your function that you need to keep track of. It's slightly different from JavaScript because each instance of the function in Dart will have its own state for isDefined. I'm not sure if it's possible or easy to get multiple instances of the function in JavasScript, but you might need to make isDefined static so that the value is shared across all instances.
Dart does not allow you to add or remove member variables from an instance of a class at runtime. Rewriting your example in Dart it might look something like this:
class doStuff {
bool isDefined;
doStuff() {
isDefined = true;
}
void stuff() {
print('The function stuff was called!');
}
}
main() {
new doStuff().stuff();
}
If you wanted to add a property bag to a class in Dart you would write:
class PropertyObject {
Map<String, Dynamic> properties;
PropertyObject() {
properties = new Map<String, Dynamic>();
}
Dynamic operator[](String K) => properties[K];
void operator[]=(String K, Dynamic V) => properties[K] = V;
}
main() {
PropertyObject bag = new PropertyObject();
bag['foo'] = 'world';
print('Hello ${bag['foo']}');
}
Note that you can't access map properties using the '.' operator.

Resources