I managed to two-way-bind my Angular.dart model to paper elements using the bind- syntax:
<paper-input bind-value="item.name"></paper-input>
Now I want to create a custom component that can expose a property for two-way binding:
#CustomTag('px-test')
class PxTest extends PolymerElement {
#published
var data = 1;
}
used like:
<px-test bind-data="item.data"></px-test>
The component gets rendered, and the data-field, referenced in the component template with {{data}} is rendered correctly, but the binding of data to item.data is not happening, i.e. if item.data is 55 the component still renders 1. Angular also tries to create the binding, a watch on item.data is created, but the changes are not propagated to PxTest.data What do I have to change in PxTest to make the binding happening?
Versions: Angular: 1.0, Polymer: 0.15.1+3
I don't know details about how binding between Angular.dart and Polymer.dart works but I suggest you try
//#published
#PublishedProperty(reflect: true)
var data = 1;
this way the DOM attribute gets updated too.
Related
I have an Angular Dart page where I need to create a component on the screen for each item in a collection. The items are custom model objects:
class CohortDataSourceAssay{
String name;
String displayName;
bool selected;
List<String> platforms = new List<String>();
CohortDataSourceAssay();
}
I have a parent page where I want to create a template for each element in a collection of the class above:
<data-source-assay *ngFor="let assay of dataSource.assays"></data-source-assay>
Here is the markup for the data-source-assay component:
<div class="dataSourceAssay">
<material-checkbox [(ngModel)]="assay.selected" (ngModelChange)="onCbxChange($event)">{{assay.displayName}}</material-checkbox>
<material-dropdown-select class="selectStyle"
[disabled]="!assay.selected"
[buttonText]="platformLabel"
[selection]="assaySequencingPlatforms"
[options]="sequencingPlatforms"
[itemRenderer]="itemRenderer">
</material-dropdown-select>
</div>
This works insofar as it loads a block for each assay element in dataSource.assays, however the assay block does not appear to get the assay model object. It appears to be null. How do I pass it in?
You need to declare an #Input() on your <data-source-assay> component, through which you can pass the assay value.
#Component(...)
class DataSourceAssayComponent {
// An input makes this property bindable in the template via []
// notation.
//
// Note: I'm not actually sure what the type of `assay` is in your
// example, so replace `Assay` with whatever the correct type is.
#Input()
Assay assay;
}
Now in your template where you create this component, you can bind the assay value to the input.
<data-source-assay
*ngFor="let assay of dataSource.assays"
[assay]="assay">
</data-source-assay>
Remember that the local values in a template are local to that template. Meaning the assay you were declaring in your ngFor isn't visible anywhere outside of that current template.
I am having trouble determining the type of a given jQueryUI widget instance.
The jQueryUI documentation for the Widget Factory suggests two techniques. From the "Instance" section:
The widget's instance can be retrieved from a given element using the
instance() method. [...]
If the instance() method is called on an element that is not
associated with the widget, undefined is returned.
the :data selector can also determine whether an element has a given
widget bound to it.
Based on their examples, let's say I initialize a datepicker and later code checks if it is a datepicker:
<p>Date: <input type="text" id="datepicker"> </p>
$(function() {
$("#datepicker").datepicker();
// ...
var i = $("#datepicker").progressbar("instance"); // i is undefined as expected
console.log(i);
var b = $("#datepicker").is(":data('ui-datepicker')"); // b = false, not sure why
console.log(b);
var i2 = $("#datepicker").datepicker("instance"); // this throws an exception
console.log(i2);
});
Based on the documentation I expected the .is call to return true, and the last line to return the instance (not throw an exception.)
JSFiddle is here. (You will need to open the browser's console to see the logged output.)
It turns out the techniques I listed above do work for many jQueryUI widgets, e.g. button, progressbar.
But datepicker is kind of weird. Looking at the DOM after a datepicker is initialized, I see the datepicker is inserted as a new element after the named element.
To get the datepicker widget instance I'd need to navigate the DOM starting from the named element. To check if the input field has a datepicker on it we can simply check the element for the class hasDatepicker:
var isDatePicker = $("#datepicker").is(".hasDatepicker");
This works with jQueryUI 1.11.2, and based on other SO questions it's been working since 2009. So I guess it's a reliable technique, but I'm not sure if its documented anywhere, or guaranteed for future versions.
I have a dart-polymer component mediator-form that I would like to add programmatically to another component. That I have done successfully. However, mediator-form is used several times. For my purpose I would like to pass #published data in the form
<mediator-form mediator='Medication'>
where the published mediator data is used.
My problem is I don't know how to set the mediator='Medication' programmatically.
My attempt is shown below
.html
<link rel='import' href='mediator_form.html'>
.dart
var newElem = new Element.tag('mediator-form')
..attributes['mediator'] = 'Medication';
does not work. newElement does not have a setProperty() method so it does not seem possible.
Any help is appreciated. Thanks.
This should work
var newElem = new Element.tag('mediator-form')
..attributes['mediator'] = 'Medication';
maybe it only works after you added it to the DOM (haven't tried myself this way).
This should also work:
var newElem = (new Element.tag('mediator-form') as MediatorForm)
..mediator = 'Medication';
If it doesn't you probably haven't imported the element.
You can set value directly on dart object, but to have that object you have to wait at least one cycle of event loop to give polymer a chance to instantiate your object in a DOM:
document.body.append(new Element.tag("mediator-form"));
// Delaying the following after element is instantiated
Timer.run((){
MediatorForm form = document.body.querySelector('mediator-form');
form.mediator = "Medication";
});
Is it possible to define an angular-dart component and then programmatically create an instance of that component and add it to your web page? I'd hoped there might be something like:
import 'package:web_sandbox/web_sandbox.dart';
import 'package:angular/angular.dart' as ng;
void main() {
document.body.appendHtml('<web-sandbox-component></web-sandbox-component>');
var node = document.body.query('web-sandbox-component');
ng.compile(node);
}
is there away of creating an angular web component programmatically and adding it to the page, maybe like the above pseudo-example, and if so how?
I don't think this is possible with Angular.
You can add an HTML tag <web-sandbox-component> into the DOM and tell Angular it should process this new HTML and then Angular would instantiate the Angular component for this tag (this is what the question you linked is about).
I don't see this as a limitation.
Is there something you would like to do that seems not possible this way?.
EDIT
Your code in main should look like this:
my document looks like
...
<body>
<div id="mydiv"></div>
...
</body>
and I append the <web-sandbox-component> to the div
main() {
print('main');
ng.Injector inj = ngaf.applicationFactory().addModule(new MyAppModule()).run();
var node = dom.querySelector('#mydiv');
node.append(new dom.Element.html('<web-sandbox-component></web-sandbox-component>', validator: new dom.NodeValidatorBuilder()..allowCustomElement("web-sandbox-component")));
ng.Compiler compiler = inj.get(ng.Compiler);
ng.DirectiveMap directiveMap = inj.get(ng.DirectiveMap);
compiler(node.childNodes, directiveMap)(inj, node.childNodes);
}
I have a page made of custom components. In that page I have a button. If I click the button I have to call another page (page.mxml consisting of custom components). Then click event handler is written in Action-script, in a separate file.
How to make a object of an MXML class, in ActionScript? How to display the object (i.e. the page)?
My code:
page1.mxml
<comp:BackgroundButton x="947" y="12" width="61" height="22"
paddingLeft="2" paddingRight="2" label="logout" id="logout"
click="controllers.AdminSession.logout()"
/>
This page1.mxml has to call page2.mxml using ActionScript code in another class:
static public function logout():void {
var startPage:StartSplashPage = new StartSplashPage();
}
Your Actionscript class needs a reference to the display list in order to add your component to the stage. MXML is simply declarative actionscript, so there is no difference between creating your instance in Actionscript or using the MXML notation.
your function:
static public function logout():void {
var startPage:StartSplashPage = new StartSplashPage();
}
could be changed to:
static public function logout():StartSplashPage {
return new StartSplashPage();
}
or:
static public function logout():void {
var startPage:StartSplashPage = new StartSplashPage();
myReferenceToDisplayListObject.addChild( startPage );
}
If your actionscript does not have a reference to the display list, than you cannot add the custom component to the display list. Adding an MXML based custom component is no different than adding ANY other DisplayObject to the display list:
var mySprite:Sprite = new Sprite();
addChild(mySprite)
is the same as:
var startPage:StartSplashPage = new StartSplashPage();
myReferenceToDisplayListObject.addChild( startPage );
Both the Sprite and the StartSplashPage are extensions of DisplayObject at their core.
You reference MVC in the comments to another answer. Without knowing the specific framework you've implemented, or providing us with more code in terms of the context you are trying to perform this action in, it is difficult to give a more specific answer.
I assume that you are on a page with a set of components and want to replace this set of components on the page with a different set of components. My apologies in advance if this is not what you are trying to do.
You can do this using ViewStacks and switching the selected index on selection -- this can be done either by databinding or by firing an event in controllers.AdminSession.logout() and listening for that event in the Main Page and switching the selectedIndex of the view stack in the handler function.
MainPage.mxml
<mx:ViewStack>
<views:Page1...>
...
<comp:BackgroundButton x="947" y="12" width="61" height="22"
paddingLeft="2" paddingRight="2" label="logout" id="logout"
click="controllers.AdminSession.logout()"/>
</views:Page1...>
<views:Page2 ...>
...
<comp:Comp1 .../>
<comp:Comp2 .../>
</views:Page2>
I think you may use state to do you work.
You may take a look at http://blog.flexexamples.com/2007/10/05/creating-view-states-in-a-flex-application/#more-221
Edit:
I am not sure I fully understand your case.
As I know, you may make a new state in page1.mxml, and name it, eg. secondPageState, and then put the custom component page2.mxml in the secondPageState.
In the controller, you need an import statement to import the page1 component and make a public var for the page1 component, eg. firstPage.
Then, the code will similar to:
public function logout():voild
{
firstPage.currentState = "secondPageState";
}
Another solution:
If you don't like the change state solution, you may try to use the addchild, to add the custom component to your application.