Why doesn't browser re-render when controller updates? - dart

For some reason when a member variable of my controller gets changed, which is linked to in my HTML, the browser re-render to show the new variable until I type in a input box on the same page. I'd of expected
{{SignInCtrl.userLoggedIn}}
to get updated automatically when bool userLoggedIn is changed.
Controller
import 'package:angular/angular.dart';
import 'package:js/js.dart' as js;
import 'dart:html'; //for window.console
#NgController(
selector: '[signin-controller]',
publishAs: 'SignInCtrl')
class SignInController {
bool userLoggedIn = false;
HTML
<!DOCTYPE html><html ng-app>
<head><meta charset='UTF-8'>
<script src='//cdnjs.cloudflare.com/ajax/libs/modernizr/2.7.1/modernizr.dev.js'></script>
<link rel='stylesheet prefetch' href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css'>
<style>.ng-hide{
display: none !important;
}
.ng-show {
}
#auth {
border: none;
}
#media screen and (max-width: 740px) {
#auth button {
width: 100%;
}
}</style></head><body>
<main ng-cloak signin-controller>
<nav class="navbar navbar-default" role="navigation" ng-controller="SignInCtrl">
<span>
Is user logged in: {{SignInCtrl.userLoggedIn}}
</span>
</nav>
</main>
<script type="text/javascript" src="packages/browser/dart.js"></script>
<script src="packages/browser/interop.js"></script>
<script src='https://cdn.firebase.com/v0/firebase-simple-login.js'></script>
<script src="https://cdn.firebase.com/v0/firebase.js"></script>
<script src="packages/shadow_dom/shadow_dom.min.js"></script>
<script type="application/dart" src="main.dart"></script>
</body>
</html>
main.dart
import 'package:angular/angular.dart';
#MirrorsUsed(override: '*') //used to make js output files smaller
import 'dart:mirrors';
import 'package:my_app/app_module.dart';
void main() {
ngBootstrap(module: new AppModule());
}

Related

Setting custom validation| new paper-input / paper-input-decorator component in paper-element 0.0.6.0+4

My custom validation on my paper-input does not work anymore since the new paper-input / paper-input-decorator components.
I have the following but the validation is not triggered.
.dart
import 'package:polymer/polymer.dart';
import 'package:paper_elements/paper_input_decorator.dart';
import 'package:paper_elements/paper_button.dart';
import 'package:core_elements/core_input.dart';
import 'package:core_elements/core_icon.dart';
import 'package:epimss_reg/epimss_reg.dart' show Language;
import 'package:epimss_shared/epimss_shared.dart';
import 'dart:html';
/// A Polymer `<main-app>` element.
#CustomTag('main-app')
class MainApp extends PolymerElement {
PaperButton pprBtn;
CoreIcon coreIcon;
/// Constructor used to create instance of MainApp.
MainApp.created() : super.created();
void onInputHandler(e)
{
var decorator = $['first-input-decor'] as PaperInputDecorator;
var input = $['first'] as CoreInput;
//bool invalid = decorator.isInvalid = !input.validity.valid;
print(input.value.length);
if (input.value.length <= 6 )
{
input.setCustomValidity("Give me more!");
}
else
{
input.setCustomValidity('');
}
}
#override
void attached()
{
super.attached();
pprBtn = $['ppr-btn'];
coreIcon = $['core-icon'];
}
}
.html
<!-- import polymer-element's definition -->
<link rel='import' href='../../packages/polymer/polymer.html'>
<link rel='import' href='../../packages/paper_elements/paper_button.html'>
<link rel='import' href='../../packages/paper_elements/paper_input.html'>
<link rel='import' href='../../packages/paper_elements/paper_input_decorator.html'>
<link rel='import' href='../../packages/core_elements/core_icons.html'>
<link rel='import' href='../../packages/core_elements/core_icon.html'>
<polymer-element name='main-app'>
<template>
<style>
:host {
display: block;
}
</style>
<p>
<paper-button
id='ppr-btn'
label='button'>
<core-icon
id='core-icon'
icon='refresh'></core-icon>
My Button</paper-button>
</p>
<p>
<paper-input-decorator floatingLabel validateImmediately
id='first-input-decor'
label='First'>
<input required is='core-input'
id='first'
value='{{language.first}}'
on-input='{{onInputHandler}}'
error='Input is requried'>
</paper-input-decorator>
</p>
</template>
<script type='application/dart' src='main_app.dart'></script>
</polymer-element>
I cannot seem to associate the validation on the decorator with the input.
Thanks

Databinding not working in Polymer Dart

The subject line of the question is a bit ambiguous. I have an main entry file to load (entry.html) which uses a entry.dart script. In the entry.html, I use a custom polymer element card-table. cardtable.html is a simple list. When I load the entry.html first time, everything is good.. I see multiple rows of text printed with static data in my model list. My entry.html has a button, clicking which changes the data model (through entry.dart, I invoke the cardtable.dart). I see the right methods being called and data model change is confirmed, but UI is not updated.
entry.html
<link rel="import" href="cardtable.html">
<link rel="import" href="packages/paper_elements/paper_button.html">
<script async src="packages/browser/dart.js"></script>
<script async type="application/dart" src="entry.dart"></script>
<link rel="stylesheet" href="entry.css">
</head>
<body>
<paper-button id="inc_btn" label="+" raisedButton></paper-button>
<paper-button id="dec_btn" label="-" raisedButton></paper-button>
<card-table></card-table>
</body>
entry.dart
var tablec;
void main() {
initPolymer().run(() {
Polymer.onReady.then((_) {
tablec = new Element.tag('card-table');
var incBtn = querySelector('#inc_btn');
incBtn.onClick.listen(increment);
});
}
void increment(Event e) {
new Future(() {
tablec.increment();
});
}
}
card-table.html
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="card-table">
<template>
<style>
:host {
display: block;
color: green;
}
</style>
<content>
<div id="dynamic_area">
<template repeat="{{item in list}}">
<span>ABCD : {{item}}</span>
</template>
</div>
</content>
</template>
<script type="application/dart" src="cardtable.dart"></script>
</polymer-element>
cardtable.dart
#CustomTag('card-table')
class CardTable extends PolymerElement {
#observable List list = toObservable(['a', 'b', 'c']);
CardTable.created() : super.created() {
polymerCreated();
}
void increment() {
print('INCREMENT'); //is called on clicking + button on entry.html
list.add('d');
}
}
You call increment on a new <card-table> you reference using a variable, not the one inside your <body> tag.
Instead of
tablec = new Element.tag('card-table');
you use use
tablec = querySelector('card-table');

Dynamically creating new tag in main window of core-drawer-panel

I have the following drawer-form component
drawer-form.html
<!DOCTYPE html>
<link rel="import" href="../../../packages/polymer/polymer.html">
<link rel="import" href="../../../packages/paper_elements/paper_icon_button.html">
<polymer-element name='drawer-form'>
<template>
<section id='reg' layout horizontal center>
<paper-icon-button
icon="menu"
id='menu_icon'
on-click='{{clickHandler}}'>
</paper-icon-button>
<h4 id='regLbl'>New Patient</h4>
</section>
</template>
<script type="application/dart">
import 'package:polymer/polymer.dart';
import 'dart:html';
#CustomTag( 'drawer-form' )
class DrawerForm extends PolymerElement {
#observable bool state = false;
DrawerForm.created() : super.created();
void clickHandler( ) {
fire( 'CREATE_NEW_PATIENT' );
}
}
</script>
</polymer-element>
The drawer-form is used in a main-form component:
main-form.html
<!DOCTYPE html>
<link rel="import" href="../../../packages/polymer/polymer.html">
<link rel="import" href="../../../packages/core_elements/core_drawer_panel.html">
<link rel="import" href="../../../packages/core_elements/core_icon_button.html">
<link rel="import" href="../../../packages/core_elements/core_toolbar.html">
<link rel="import" href="../../../packages/paper_elements/roboto.html">
<link rel="import" href="../../../packages/core_elements/core_toolbar.html">
<link rel="import" href="../../../packages/paper_elements/paper_icon_button.html">
<link rel="import" href="../../../packages/fontawesome_elements/fontawesome_icon.html">
<link rel="import" href="drawer-form.html">
<polymer-element name="main-form">
<template>
<core-drawer-panel id="core_drawer_panel">
<section id="drawer" drawer>
<drawer-form></drawer-form>
</section>
<section id="main" main>
<core-toolbar id="core_toolbar">
<paper-icon-button
icon="menu"
id='menu_icon'
on-click='{{menu_icon_handler}}'>
</paper-icon-button>
<div id="div" flex>Toolbar</div>
</core-toolbar>
<section id='content'></section>
</section>
</core-drawer-panel>
</template>
<script type="application/dart">
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'package:core_elements/core_drawer_panel.dart';
#CustomTag( 'main-form' )
class MainForm extends PolymerElement {
CoreDrawerPanel drawerPanel;
MainForm.created() : super.created();
void toggleDrawer() {
bool state = drawerPanel.narrow;
}
void menu_icon_handler() {
bool state = drawerPanel.narrow;
print ( state );
}
#override
void attached() {
super.attached();
drawerPanel = $['drawerPanel'] as CoreDrawerPanel;
}
}
</script>
</polymer-element>
The clickHandloer in drawer-form.html fires a 'CREATE_NEW_PATIENT' event. How do I capture this event in the main-form component to dyanmically create the new-patient?
You should only use lowercase characters and dash for the event name (I very recently saw a bug report that this doesn't work).
I don't think anybody is able to catch an event fired from an element not yet attached to the DOM.
The constructor is therefore a bad place to put your 'fire' code to, use attached() (after super.attached()) instead.
Then you can listen in code like
// main-form
#override
void attached() {
super.attached();
this.shadowRoot.querySelector('drawer-form').on['create-new-patient'].listen((e) {
print('create-new-patient received');
}
}
or declaratively
<drawer-form on-create-new-patient='{{myEventHandlerInMainForm}}'>

When dynamically adding dart polymer elements, how do I get observable variables to on DOM

I am trying to change the default web application that uses the polymer library so that the polymer element is created and added to the DOM from DART code rather than including in the HTML. I have succeeded in adding the element to the DOM, but my observable variable are not being updated on the DOM. The events are being fired, and the values are changing. I have got the DOM to update using Observable.dirtyCheck(), however, this is apparently expensive, so am trying to figure out how to get polymer to update dom without dirtyCheck().
So, In short, how to I get rid of Observable.dirtyCheck()???
dynamiccreate.dart
library dynamiccreate;
import 'dart:html';
import 'package:polymer/polymer.dart';
main() {
initPolymer();
//create click-counter element at runtime from DART, not HTML
var NewElement = new Element.tag('click-counter');
NewElement.setAttribute("count", "5");
//Add to DOM
querySelector('#sample_container_id').children.add(NewElement);
}
dynamiccreate.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample app</title>
<link rel="stylesheet" href="dynamiccreate.css">
<!-- import the click-counter -->
<link rel="import" href="clickcounter.html">
<!-- <script type="application/dart">export 'package:polymer/init.dart';</script> -->
<script src="packages/browser/dart.js"></script>
</head>
<body>
<h1>DynamicCreate</h1>
<p>Hello world from Dart!</p>
<div id="sample_container_id">
<!-- <click-counter count="5"></click-counter> -->
</div>
<script src="dynamiccreate.dart" type="application/dart"></script>
</body>
</html>
clickcounter.dart
import 'package:polymer/polymer.dart';
/**
* A Polymer click counter element.
*/
#CustomTag('click-counter')
class ClickCounter extends PolymerElement {
#published int count = 0;
ClickCounter.created() : super.created() {
}
//increment gets called when dynamically adding object at runtime
//But does not update count on DOM
void increment() {
count++;
//Have to add this to update count in DOM
Observable.dirtyCheck(); //<<<---How do I get rid of this???
}
}
clickcounter.html
<polymer-element name="click-counter" attributes="count">
<template>
<style>
div {
font-size: 24pt;
text-align: center;
margin-top: 140px;
}
button {
font-size: 24pt;
margin-bottom: 20px;
}
</style>
<div>
<button on-click="{{increment}}">Click me</button><br>
<span>(click count: {{count}})</span>
</div>
</template>
<script type="application/dart" src="clickcounter.dart"></script>
</polymer-element>
Change your dynamiccreate.dart file to look like this, and the counter starts incrementing in the UI:
library dynamiccreate;
import 'dart:html';
import 'package:polymer/polymer.dart';
main() {
initPolymer().run(() {
var newElement = new Element.tag('click-counter');
newElement.setAttribute("count", "15");
querySelector('#sample_container_id').children.add(newElement);
});
}
Nit: name your variable newElement, not NewElement. Fixed here.

How do I dynamically load HTML and insert into my web page with Dart?

How do I dynamically load a snippet of HTML and insert it into my web page? I am using Dart.
Glad you asked! Using Dart for this task isn't much different than JavaScript, except you get typing, code completion, and a slick editing experience.
First, create the snippet.html:
<p>This is the snippet</p>
Next, create the application. Notice the use of XMLHttpRequest to request the snippet. Also, use new Element.html(string) to create a block of HTML from a string.
import 'dart:html';
void main() {
var div = querySelector('#insert-here');
HttpRequest.getString("snippet.html").then((resp) {
div.append(new Element.html(resp));
});
}
Finally, here's the host HTML page:
<!DOCTYPE html>
<html>
<head>
<title>dynamicdiv</title>
</head>
<body>
<h1>dynamicdiv</h1>
<div id="insert-here"></div>
<script type="application/dart" src="dynamicdiv.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
main.dart:
import 'dart:html';
DivElement div = querySelector('div');
main() async {
String template = await HttpRequest.getString("template.html");
div.setInnerHtml(template, treeSanitizer: NodeTreeSanitizer.trusted);
}
template.html:
<h1>Hello world.</h1>
Check my bird... <em>it flies</em> !
<img src="https://www.dartlang.org/logos/dart-bird.svg">
For the full example, that runs out of the box, see:
https://gist.github.com/kasperpeulen/536b021ac1cf397d4e6d
Note that you need 1.12 to get NodeTreeSanitizer.trusted working.
You can try this example.
https://jsfiddle.net/kofwe39d/ (JS compiled from Dart source code.)
web/main.dart
import 'dart:async';
import 'dart:html';
import 'package:virtual_dom/components/component.dart';
import 'package:virtual_dom/features/state.dart';
import 'package:virtual_dom/helpers/h.dart';
import 'package:virtual_dom/helpers/mount.dart';
import 'package:virtual_dom/helpers/styles.dart';
import 'package:virtual_dom/helpers/vhtml.dart';
void main() {
final app = document.getElementById('app')!;
mount(app, _App());
}
class _App extends Component {
#override
Object render() {
final timer = State.get('timer', () => 3);
final setTimer = State.set<int>('timer');
if (timer > 0) {
Timer(Duration(seconds: 1), () {
setTimer(timer - 1);
});
}
final html = timer > 0
? ''
: '''
Hello, <strong>World!</strong>
''';
final style = styles({'padding': '6px'});
return h('div', {
'style': style
}, [
if (timer > 0) '$timer sec',
h('p', 'Your html:'),
vHtml('div', html),
]);
}
}
web/index.html
<!DOCTYPE html>
<html style="height: 100%;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example application</title>
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart.js"></script>
</head>
<body style="height: 100%; font-family: Verdana,sans-serif; font-size:15px; line-height:1.5">
<div id="app" style="height: 100%;"></div>
</body>
</html>

Resources