Client-side, then() or other? - dart

How i can use "Future" in client-side ?
And, how I can block the execution of my code, while no event is catch ?
import 'dart:html';
import 'dart:convert';
import 'dart:async';
Map data;
Future<String> ft_get_pseudo()
{
InputElement button;
InputElement text;
text = querySelector('[name="pseudo"]');
button = querySelector('[name="push"]');
button.onClick.listen((_) => text.value);
}
void main()
{
WebSocket wss;
String encode;
data = new Map();
wss = new WebSocket('ws://127.0.0.1:4040/ws');
ft_get_pseudo().then((name)
{
data['pseudo'] = name;
encode = JSON.encode(data);
wss.onOpen.listen((_) => wss.send(encode));
wss.onMessage.listen((msg) => print("Msg received : ${msg.data}"));
});
}
I saw Promise function in ecmascript 6, there is a way to use it, or the idea ?
HTML :
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<script type="application/dart" src="client.dart"></script>
<link rel="stylesheet" href="style.css" type="text/css">
<title>Client</title>
</head>
<body>
<div id="console">
</div>
<input type="text" name="pseudo" size="20" placeholder="pseudo">
<input type="button" name="push" value="Send">
</body>
</html>

For such a simple use case you can do it this way
Future<String> ft_get_pseudo()
{
return new Future(() {
InputElement button;
InputElement text;
text = querySelector('[name="pseudo"]');
button = querySelector('[name="push"]');
button.onClick.listen((_) => _completer.complete(text.value));
}
}

If I understand you correctly, you want to get text.value from the ft_get_pseudo() function when you push on the button, right? If so, you need to create a new Completer and return its Future at the end of the ft_get_pseudo(). Then, in the button's onClick event, you just complete the future with the value of text.value.
Code might be something like this:
Future<String> ft_get_pseudo()
{
Completer _completer = new Completer();
InputElement button;
InputElement text;
text = querySelector('[name="pseudo"]');
button = querySelector('[name="push"]');
button.onClick.listen((_) => _completer.complete(text.value));
return _completer.future;
}

I think you want to do something like this, but I don't yet fully understand what you try to accomplish.
Can you please just add a comment what you need differently?
Map data;
void main() {
//(querySelector('[name="push"]') as ButtonInputElement).onClick.listen(btnClickHandler);
(querySelector('[name="push"]') as ButtonInputElement).onClick.first.then(btnClickHandler);
// this would work too, because every element has the click event.
// querySelector('[name="push"]').onClick.listen(btnClickHandler);
}
void btnClickHandler(MouseEvent e) {
String name = (querySelector('[name="pseudo"]') as TextInputElement).value;
data = {'pseudo': name};
String encode = JSON.encode(data);
WebSocket wss = new WebSocket('ws://127.0.0.1:4040/ws');
wss.onOpen.listen((_) => wss.send(encode));
wss.onMessage.listen((msg) => print("Msg received : ${msg.data}"));
}

Related

How to Remove Client-Side Validation on a textboxfor for multiple emails?

I am creating an MVC application in which I will have an input field for a list of emails. In order to do so, I added multiple in order to allow for the user to enter a comma separated list of emails. By doing it this way, I'm able to have input controls to check for the email(s) to be properly formatted (".+#gmail.com").
The problem is that when I test this, it automatically adds class="input-validation-error" (even if I set the #class="" prior) and will not allow me to post due to an invalid input, as a result. Is there any way to allow for this, or is my only option to make it an Email string property and parse it by commas into the EmailList property in the controller?
(Here is my code):
View:
#Html.TextBoxFor(model => model.EmailList, new { type = "email", placeholder
= "ex#gmail.com (',' Delimited)", title = "Make sure your email(s) are
formatted appropriately (and comma separated).", multiple = "" })
Model:
public List<string> EmailList { get; set; }
UPDATE:
I should also add that I am performing json serialization on post, so It needs to be in the form of a list. Ideally, I would be able to use the multiple for the input of type email tag, since it would allow for the necessary input controls that I would need without making me take it as a string and writing it to a list.
The new fiddle is here, click on it https://dotnetfiddle.net/ORYDVJ
View
#model Testy20161006.Controllers.MurphyModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Tut122</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("#emailField").change(function () {
var theList = {
emaillist: []
};
var array = $('#emailField').val().split(",");
$.each(array, function (i) {
theList.emaillist.push(
array[i]
);
});
$.ajax({
url: '/Home/Tut122',
traditional: true,
type: "POST",
contentType: "application/json",
data: JSON.stringify({ murphyModel: theList }),
success: function (data) {
console.log('success!!');
$("#theOutput").html(data)
}
});
})
})
</script>
</head>
<body>
#Html.TextBoxFor(model => model.EmailList, new
{
id = "emailField",
type = "email",
placeholder = "ex#gmail.com (',' Delimited)",
title = "Make sure your email(s) are formatted appropriately (and comma separated).",
multiple = ""
})
<span>The output data:</span>
<div id="theOutput">
</div>
</body>
</html>
Controller/View Model
public class MurphyModel
{
public List<string> EmailList { get; set; }
}
public class HomeController : Controller
{
[HttpPost]
public string Tut122(MurphyModel murphyModel)
{
//You need to get Newtonsoft.JSON
var json = JsonConvert.SerializeObject(murphyModel);
return json;
}
public ActionResult Tut122()
{
MurphyModel model = new MurphyModel();
return View(model);
}
https://dotnetfiddle.net/eadTjh
View
#model Testy20161006.Controllers.MurphyModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Tut122</title>
</head>
<body>
#if (ViewBag.Output != null)
{
<span>#ViewBag.Output</span>
}
#using (Html.BeginForm())
{
#Html.TextBoxFor(model => model.EmailList, new
{
type = "email",
placeholder = "ex#gmail.com (',' Delimited)",
title = "Make sure your email(s) are formatted appropriately (and comma separated).",
multiple = ""
})
<input type="submit" value="submit" />
}
</body>
</html>
Controller/View Model
namespace Testy20161006.Controllers
{
public class MurphyModel
{
//We don't want a list class, rather a string
public string EmailList { get; set; }
}
public class HomeController : Controller
{
[HttpPost]
public ActionResult Tut122(MurphyModel model)
{
var splitEmails = model.EmailList.Split(',');
var anEmail = "These are the different emails: ";
foreach (string email in splitEmails)
{
//set breakpoint here
anEmail+= email + " and ";
}
anEmail = anEmail.Substring(0, anEmail.Length - 5);
ViewBag.Output = anEmail;
return View(model); }
public ActionResult Tut122()
{
MurphyModel model = new MurphyModel();
return View(model);
}
add a js file hopefully u use jQuery
$(document).ready(function () {
$("#EmailList").removeClass("input-validation-error");
});
After Reviewing kblau's answer, I realized that was partially the reason. The other issue that I was running into (where MVC was stepping over any of my manually entered client-side validation) was the result of the unobtrusive validation:
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
After commenting this out, it allowed for me to have the input write to a string Email which I would then assign to a list of strings EmailList in the controller. This ended up working for me.

Removing disallowed type extension <INPUT is="db-edit">

I previously used DARTEDITOR, and an older version of DART SDK (1.10).
I've updated the SDK, and began to use WebStorm.
And I got an error:
Removing disallowed type extension <INPUT is = "db-edit">
class DBEditText extends InputElement { String _FieldName = "";
DBEditText.created() : super.created() {
//type = "text";
this.classes.add("editElement"); }
String DBGetValue() {
return this.value; }
void DBSetValue(String val) {
this.value = val; } ....
document.registerElement('db-edit', DBEditText, extendsTag: 'input');
....
HTML
input type='text' id='enum' is='db-edit' size=15
What could be the problem?
I can't reproduce the error
import 'dart:html';
void main() {
document.registerElement('db-edit', DBEditText, extendsTag: 'input');
document.querySelector('button').onClick.listen((e) {
var inp = document.querySelector('input');
print(inp.runtimeType);
});
}
class DBEditText extends InputElement {
String _FieldName = "";
DBEditText.created() : super.created() {
//type = "text";
this.classes.add("editElement");
}
String DBGetValue() {
return this.value;
}
void DBSetValue(String val) {
this.value = val;
}
}
<!DOCTYPE html>
<html>
<body>
<div>input:
<input type='text' id='enum' is='db-edit' size=15>
</div>
<button>click</button>
<script type="application/dart" src="index.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
Clicking the button prints
DBEditText
Update
For the element to be added dynamically you might need a NodeValidator
NodeValidator validator = new NodeValidatorBuilder()
..allowCustomElement('INPUT', attributes: ['is']);
document.querySelector('body')
.appendHtml("<input type='text' id='enum' is='db-edit' size=15>", validator: validator);

Adding dynamic WebComponent divs

I'm trying to dynamically add a number of divs using Dart. The divs contain a custom web component, and I'm trying to pass in a variable. I want to be able to specify n number of variables, pass them to n number of components, and insert those into an HTML document. What's happening, however, is I'm getting the inserted divs without the variables. I wonder if this is a case of Dart trying to pass something into a an already loaded DOM and therefore doing nothing...? Here's some code:
product_elem.dart:
import 'package:web_ui/web_ui.dart';
import 'dart:html';
class ProductComponent extends WebComponent {
var productId;
}
product_elem.html:
<!DOCTYPE html>
<html>
<body>
<element name="product-elem" constructor="ProductComponent" extends="div">
<template>
<div style="width:335px;margin:10px;">
<h3>
{{productId}}
</h3>
</div>
</template>
<script type="application/dart" src="product_elem.dart"></script>
</element>
</body>
</html>
testcase_component.dart:
import 'dart:html';
import 'package:web_ui/web_ui.dart';
var productId;
void main() {
List myList = new List();
myList.addAll(["Foo", "Bar", "Baz"]);
for (var i = 0; i < myList.length; i++) {
productId = myList[i];
query('#products').innerHtml +=
"<div is='product-elem' id='product_elem' product-id='{{productId}}'></div>";
}
}
testcase_component.html:
<!DOCTYPE html>
<html>
<head>
<link rel="import" href="product_elem.html">
</head>
<body>
<div id="products">
<!-- Insert dynamic divs here -->
</div>
<script type="application/dart" src="testcase_component.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
You can't just add WebComponents like that. WebUI doesn't know that anything was added, so you just end up with a normal div.
Here is the current (slightly messy) way to dynamically add WebComponents:
void main() {
List myList = new List();
myList.addAll(["Foo", "Bar", "Baz"]);
for (var i = 0; i < myList.length; i++) {
productId = myList[i];
var product = new ProductComponent(productId);
product.host = new DivElement();
var lifecycleCaller = new ComponentItem(product)..create();
query('#products').append(product.host);
lifecycleCaller.insert();
}
}
This way the proper WebUI lifecycles are called.
Also make sure to add a constructor for ProductElem so that productId can be externally set:
class ProductComponent extends WebComponent {
var productId;
ProductComponent(this.productId);
}

WebView.InvokeScript always returns empty string

I've got a problem with WebView control. I'm developing Windows 8 Metro Style app and I'm trying to invoke script in content of WebView, but it's always returns empty string.
I've tried to make it "WebView.InvokeScript("eval", new string[] { "document.getElementById('contentDiv').offsetHeight" }) as well but it works the same - empty string. I really have no guesses what wrong is here.
public void Sethtml(string html) {
var toSet = string.Format(Style, html);
wv.LoadCompleted += wv_LoadCompleted;
wv.NavigateToString(toSet);
}
void wv_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
WebView wv = sender as WebView;
string height = wv.InvokeScript("heightFun", new string[0]);
}
public static readonly string Style = #"<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
body {{
font-family: Segoe UI;
}}
</style>
<script type='text/javascript'>
var heightFun = function() {{
return document.getElementById('contentDiv').offsetHeight;
}}
</script>
</head>
<body>
<div id='contentDiv'>
{0}
</div>
</body>";
You must use the window.external.notify to send a value back.
See the forum post:
http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/ac390a6a-d4ad-408c-8b13-93f9694cbabe
Just solved this problem via a hint of the previous answer.
Make sure your return value is a string.

Add on-click event code to a LabelField

In my application there is a LabelField with text "www.google.com" When the user clicks, the default browser should open to www.google.com.
try this code
final LabelField label = new LabelField("http://www.google.com",LabelField.FOCUSABLE){
public boolean navigationClick (int status , int time){
BrowserSession bSession = Browser.getDefaultSession();
bSession.displayPage(label.getText());
return true;
}
};
you may use Jquery.
try this code:
<html>
<head>
<title>Opens a link</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.js"></script>
</head>
<body>
<label for="link" id="target">www.google.com</label>
<script type="text/javascript">
$('#target').click(function () {
var url = $(this).text();
window.location = "http\://"+url;
});
</script>
</body>
</html>

Resources