I created a custom element, and want to send data / parameters to it:
my element code is:
class SaveBtn extends HtmlElement {
static final tag = 'save-button';
factory SaveBtn()=>new Element.tag(tag);
SaveBtn.created() : super.created() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
// Create a standard element and set it's attributes.
var btn = new ButtonElement();
...
btn.text= this.getAttribute('data-name');
shadow.nodes.add(btn);
Element launchElement(){
return (shadow);
}
}
}
The below code in the html file worked perfectly:
<save-button data-name='save orders'></save-button>
but what if I want to use the below code, what shall I adjust in my custom element code?
new SaveBtn('save orders')
This is another solution that worked with me before reading the posted answers, I liked #Gunter answer and will adapt it.
class SaveBtn extends HtmlElement {
static final tag = 'save-button';
factory SaveBtn()=>new Element.tag(tag);
var shadow, btn;
SaveBtn.created() : super.created() {
shadow = this.createShadowRoot();
btn = new ButtonElement()
..text="save"
..style.height= '20px'
..style.borderBottom='1px solid #D1DBE9';
btn.text = this.getAttribute('data-name');
shadow.nodes..add(label)..add(btn);
}
Element launchElement(name){
btn.text= name;
return (shadow);
}
}
and called the element as:
var btn=new SaveBtn()..launchElement('click me');
name is an optional argument. When you pass a value it is used for the text attribute of the button.
I pass it just to a field (name) in the elements class and set it to the the button in attached.
When you use data-xxx attributes you can use the dataset getter.
I also changed the other code a bit. I think attached is a better place to access attributes because then the element is already upgraded properly.
class SaveBtn extends HtmlElement {
static final tag = 'save-button';
factory SaveBtn([String name]) => (new Element.tag(tag) as SaveBtn)..name = name;
ButtonElement innerButton;
ShadowRoot shadow;
SaveBtn.created() : super.created() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
// Create a standard element and set it's attributes.
innerButton = new ButtonElement();
shadow.nodes.add(innerButton);
}
String name;
#override
void attached() {
super.attached();
innerButton.text = name != null ? name : this.dataset['name'];
}
}
SaveBtn({String name, String width}) => (new Element.tag(tag) as SaveBtn)
..name = name
..style.width=width;
Below a solution proved to work.
factory SaveBtn() => new Element.tag(tag)
String name, width;
#override
void attached() {
super.attached();
innerButton.text = name != null ? name : this.dataset['name']
..style.width=width;
}
call the item as:
var btn = new SaveBtn()..name='save'..width='100%';
You can simply add a new constructor for this that sets the data-name attribute too:
class SaveBtn {
// ...
factory SaveBtn(String label) {
var btn = new Element.tag(tag);
btn.setAttribute('data-name', label); // Set properties/call methods here
return btn;
}
// ...
}
Related
I want to get TypeAnnotation source to get annotations defined on that type
// file1.dart
#Annoation(name :"hello")
class RType { }
// file2.dart
#Selectors()
class Example {
static Rtype hello() => null;
}
by using ast visitor i am able to get RType ( TypeAnnoation) , but i want to get actual RType and its annotations ..
class SelectorsGenerator extends GeneratorForAnnotation<Selectors> {
AstNode getAstNodeFromElement(Element element) {
AnalysisSession session = element.session;
ParsedLibraryResult parsedLibResult =
session.getParsedLibraryByElement(element.library);
ElementDeclarationResult elDeclarationResult =
parsedLibResult.getElementDeclaration(element);
return elDeclarationResult.node;
}
#override
generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
if (!(element is ClassElement)) {
throw Exception("Selectors should be applied on class only");
}
element = element as ClassElement;
final visitor = ExampleVisitor();
final astNode = getAstNodeFromElement(element);
astNode.visitChildren(visitor);
return """
// Selector
""";
}
}
class ExampleVisitor extends SimpleAstVisitor {
#override
visitMethodDeclaration(MethodDeclaration node) {
final t= node.returnType; //TypeAnnonation
t.type // DartType is null here :(
//TODO i want to get annotations defined on this type
}
}
You shouldn't need to switch to the AST model for this, it should be possible to get the annotation with the Element model.
var methods = classElement.methods;
for (var method in methods) {
var returnType = method.returnType;
var metadata = returnType.element.metadata;
// Do something with the annotation.
}
I have this class:
class Entry {
final String id;
final List<ListEntry> listEntries;
Entry({this.listEntries}):
id = Uuid().v4();
Entry.withId({this.id, this.listEntries});
}
// create new class instance
var e = Entry();
Now when I call any method on e.listEntries I will get a NPE because it is not initialized. Is there a way to have it default to an empty list in case the constructor argument is not provided?
You can use a Factory constructor:
class Entry {
final String id;
final List<String> listEntries;
factory Entry({List<String> listEntries}) {
return Entry._(listEntries ?? []);
}
Entry._(this.listEntries):
id = Uuid().v4();
Entry.withId({this.id, this.listEntries});
}
You can initialize the field in the initializer list instead of using this.ListEntries (an initializing formal).
class Entry {
final String id;
final List<ListEntry> listEntries;
Entry({List<ListEntry> listEntries})
: this.withId(id: Uuid().v4(), listEntries: listEntries);
Entry.withId({this.id, this.listEntries})
: listEntries = listEntries ?? [];
}
// create new class instance
var e = Entry();
Here I reuse the Entry.withId constructor so I only have to write things once.
I use table component and generate column for optiongroup.
when change optionGroup's value, and click the save button,
the table get the before value - not changed value..
How to get the chaged value ? Not origin value.
here code...
public class MyTypeColumnGenerator implements ColumnGenerator{
public Object generateCell( Table source, Object itemId, Object columnId) {
BeanItem<MyType> beanItem = (BeanItem<MyType>)source.getItem(itemId);
MyType view = beanItem.getBean() ;
if(view.getValueType().equals(ValueType.Flag)){
// radio
OptionGroup opt = new OptionGroup() ;
opt.addItem(1) ; // y
opt.addItem(0) ; // n
opt.setItemCaption(1, Messages.getString(Messages.Opt_Y));
opt.setItemCaption(0, Messages.getString(Messages.Opt_N));
opt.setStyleName("horizontal");
if(view.getFactorValue() == 0){
opt.select(0);
}else if(view.getFactorValue() == 1){
opt.select(1);
}
return opt ;
}else{
Label label = new Label();
label.setValue("N/A");
return label;
}
}
}
btnSave.addClickListener(new ClickListener() {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public void buttonClick(ClickEvent event) {
Collection<?> items = table.getItemIds() ;
for (Object item : items) {
Property pName = table.getContainerProperty(item, "name");
Property pVal = table.getContainerProperty(item, "value");
}
pVal gets only origin value , not changes value.
You have to add a ValueChangeListener to the OptionGroup and inside the listener actually set the value on your MyType view using something like view.setValue(...).
Your code would then look something like that:
OptionGroup opt = new OptionGroup() ;
opt.addValueChangeListener(new Property.ValueChangeListener() {
#Override
public void valueChange (Property.ValueChangeEvent event){
view.setValue(event.getProperty().getValue());
}
});
I would like to know if there is a binding mechanism from a viewmodel property that provides focus (the cursor to blink or something to indicate that the textedit has focus) in a specific edittext of my choice.
This is a general Mvvm question - like MVVM Focus To Textbox
Just as in the general question, in MvvmCross you could do this in some code behind in your View. For example, you could create a helper class like:
public class Helper
{
private Activity _a;
public Helper(Activity a)
{
_a = a;
}
// TODO - this should probably be a ViewModel-specific enum rather than a string
private string _focussedName;
public string FocussedName
{
get { return _focussedName; }
set
{
_focussedName = value;
var mapped = MapFocussedNameToControlName(_focussedName);
var res = _a.Resources.GetIdentifier(mapped, "id", _a.PackageName);
var view = _a.FindViewById(res);
view.RequestFocus();
}
}
private string MapFocussedNameToControlName(string value)
{
// TODO - your mapping here...
return value;
}
}
This could then be bound in the View and in OnCreate as:
private Helper _helper;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.main);
_helper = new Helper(this);
this.CreateBinding(_helper)
.For(h => h.FocussedName)
.To<MyViewModel>(x => x.FocusName)
.OneWay()
.Apply();
}
This code not tested - but should roughly work.
Like the question at Dynamic class method invocation in PHP I want to do this in Dart.
var = "name";
page.${var} = value;
page.save();
Is that possible?
There are several things you can achieve with Mirrors.
Here's an example how to set values of classes and how to call methods dynamically:
import 'dart:mirrors';
class Page {
var name;
method() {
print('called!');
}
}
void main() {
var page = new Page();
var im = reflect(page);
// Set values.
im.setField("name", "some value").then((temp) => print(page.name));
// Call methods.
im.invoke("method", []);
}
In case you wonder, im is an InstanceMirror, which basically reflects the page instance.
There is also another question: Is there a way to dynamically call a method or set an instance variable in a class in Dart?
You can use Dart Mirror API to do such thing. Mirror API is not fully implemented now but here's how it could work :
import 'dart:mirrors';
class Page {
String name;
}
main() {
final page = new Page();
var value = "value";
InstanceMirror im = reflect(page);
im.setField("name", value).then((_){
print(page.name); // display "value"
});
}
You can use Serializable
For example:
import 'package:serializable/serializable.dart';
#serializable
class Page extends _$PageSerializable {
String name;
}
main() {
final page = new Page();
var attribute = "name";
var value = "value";
page["name"] = value;
page[attribute] = value;
print("page.name: ${page['name']}");
}