javascript Dojo MVC 的简单登录实现
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10984855/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple Login implementation for Dojo MVC
提问by fneron
Is there any example on how to implement a simple login page/dialog? I have been trying to do it with dojo boilerplate (check my previous questions : Layout implementation for Dojo MVC). So far, I have been able to display my dialog box. But I want to be able to get my data and on click event want to have an alert box for example (with his content).
有没有关于如何实现简单登录页面/对话框的示例?我一直在尝试使用 dojo 样板(检查我以前的问题:Dojo MVC 的布局实现)。到目前为止,我已经能够显示我的对话框。但是我希望能够获取我的数据,并且在点击事件时想要有一个警报框(例如他的内容)。
My view:
我的观点:
<form action="Login" method="post" validate="true" id="loginForm">
<table width="258">
<tr>
<td><label>Login</label></td>
<td><input class="cell" type="text" trim="true" dojoType="dijit.form.TextBox" value="" name="login" id="userId"/></td>
</tr>
<tr>
<td><label>Password</label></td>
<td><input class="cell" type="password" trim="true" dojoType="dijit.form.TextBox" value="" name="password" id="password"/></td>
</tr>
<tr><td colspan="2"> </td></tr>
<tr>
<td colspan="2" align="center">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="center" valign="top"><button dojoType="dijit.form.Button" type="submit" id="LoginButton" onClick="connect">Ok</button></td>
<td align="left" valign="top"><button dojoType="dijit.form.Button" type="submit" onclick="document.Login.reset()" id="Cancel">Cancel</button></td>
<td><button dojoType="dijit.form.Button" type="submit" onclick="showDialog();" id="resetPassword"> Show Dialog </button></td>
</tr>
</table>
</td>
</tr>
</table>
</form>
My Widget module/class
我的小部件模块/类
define([
"dojo/_base/declare",
"dijit/_Widget",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/text!app/views/Login/Login.html",
"dijit/Dialog",
"dijit/form/Button",
"dijit/form/TextBox"
], function(
declare,
_Widget,
_TemplatedMixin,
_WidgetsInTemplateMixin,
template,
Dialog
){
return declare([_Widget, _TemplatedMixin, _WidgetsInTemplateMixin, Dialog], {
templateString: template
});
});
Now, if you check the HTML the element id LoginButton should call in this case a "connection" function. Which should show (on an alert box) the username and password current input.
现在,如果您检查 HTML,元素 id LoginButton 在这种情况下应该调用“连接”函数。其中应该显示(在警报框中)当前输入的用户名和密码。
Where do I put my function? kind of...
我把我的函数放在哪里?的种类...
connect : function(){
alert("username :" + dom.byId("userId").value()
+ " Password: " + dom.byId("password").value());
}
EDIT: New code
编辑:新代码
define([
"dojo/_base/declare",
"dijit/_Widget",
"dojo/dom",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/text!app/views/Login/Login.html",
"dijit/Dialog",
"dijit/form/Button",
"dijit/form/TextBox"
], function(
declare,
dom,
_Widget,
_TemplatedMixin,
_WidgetsInTemplateMixin,
template,
Dialog
){
return declare("login", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin, Dialog], {
templateString: template,
postCreate: function() {
this.inherited(arguments);
// make reference to widget from the node attachment
this.submitButton = dijit.getEnclosingWidget(this.submitButtonNode);
// override its onSubmit
this.submitButton.onClick = function(){
alert("username :" + dom.byId("userId").value()
+ " Password: " + dom.byId("password").value());
};
},
// and a sample on how to implement widget-in-template stateful get/setter pattern
// e.g. if submitbutton label should change on some event, call as such:
// dijit.byId('loginForm').set("submitLabel", "Sendin login, please wait");
_setSubmitLabelAttr : function(value) {
return this.submitButton.set("label", value);
},
_getSubmitLabelAttr : function() {
return this.submitButton.get("label");
},
});
});
My main.js:
我的 main.js:
define([ 'dojo/has', 'require', 'dojo/_base/sniff'], function (has, require) {
var app = {};
if (has('host-browser')) {
require([ './views/Login', 'dojo/domReady!' ], function (Login) {
app.login = new Login().placeAt(document.body);
app.login.startup();
// And now…
app.login.show();
});
}
else {
console.log('Hello from the server!');
}
});
回答by phusick
I would like to add my solution: http://jsfiddle.net/phusick/tG8Sg/
我想添加我的解决方案:http: //jsfiddle.net/phusick/tG8Sg/
It is a bit twisted due to constrains of jsFiddle, but the main principles are the same as I employ in my coding.
由于 jsFiddle 的限制,它有点扭曲,但主要原则与我在编码中采用的相同。
First of all, the login process (or any other form processing) is encapsulated inside the dialog and it communicate with the rest of the application thought emitting evens via dojo/Evented
. This is how it works:
首先,登录过程(或任何其他表单处理)被封装在对话框中,它与应用程序的其余部分进行通信,思想通过dojo/Evented
. 这是它的工作原理:
var loginDialog = new LoginDialog({ controller: loginController});
loginDialog.startup();
loginDialog.show();
loginDialog.on("cancel", function() {
console.log("Login cancelled.");
});
loginDialog.on("error", function() {
console.log("Login error.");
});
loginDialog.on("success", function() {
console.log("Login success.");
console.log(JSON.stringify(this.form.get("value")));
});
As you can see in the jsFiddle, there are two templates dialog-templateand login-form-templatewhich I assemble inside the LoginDialog
constructor. The reason is I would normally have also a class wrapping dijit/form/Form
to do some magic beyond standard dijit/form/Form
validation and data serialization, but since login is simple and it'd be a mess in the single file of jsFiddle, I got rid of it. The advantage of separating a form from a dialog is you can use the same form (i.e. View) together with all the form ad hoc code somewhere else, e.g. in a ContentPane
. The form is there just to display and gather data to/from user, it should not directly communicate with Model, i.e. web service, there is a Controllerfor that purpose:
正如您在 jsFiddle 中看到的,我在构造函数中组装了两个模板dialog-template和login-form-templateLoginDialog
。原因是我通常也会有一个类包装dijit/form/Form
来做一些超出标准dijit/form/Form
验证和数据序列化的魔法,但由于登录很简单,而且它在 jsFiddle 的单个文件中会很混乱,我摆脱了它。将表单与对话框分开的优点是您可以将相同的表单(即View)与其他地方的所有表单即席代码一起使用,例如在ContentPane
. 表单只是为了向/从用户显示和收集数据,它不应该直接与Model通信,即 web 服务,有一个控制器为了这个目的:
var LoginController = declare(null, {
constructor: function(kwArgs) {
lang.mixin(this, kwArgs);
},
login: function(data) {
// simulate calling web service for authentication
var def = new Deferred();
setTimeout(lang.hitch(this, function() {
def.resolve(data.username == this.username && data.password == this.password);
}), 1000);
return def;
}
});
Create an instance of LoginController
:
创建一个实例LoginController
:
// provide username & password in the constructor
// since we do not have web service here to authenticate against
var loginController = new LoginController({username: "user", password: "user"});
and pass it to LoginDialog
constructor as yet seen above:
并将其传递给LoginDialog
构造函数,如上所示:
var loginDialog = new LoginDialog({ controller: loginController});
Finally LoginDialog
class:
最后LoginDialog
类:
var LoginDialog = declare([Dialog, Evented], {
READY: 0,
BUSY: 1,
title: "Login Dialog",
message: "",
busyLabel: "Working...",
// Binding property values to DOM nodes in templates
// see: http://www.enterprisedojo.com/2010/10/02/lessons-in-widgetry-binding-property-values-to-dom-nodes-in-templates/
attributeMap: lang.delegate(dijit._Widget.prototype.attributeMap, {
message: {
node: "messageNode",
type: "innerHTML"
}
}),
constructor: function(/*Object*/ kwArgs) {
lang.mixin(this, kwArgs);
var dialogTemplate = dom.byId("dialog-template").textContent;
var formTemplate = dom.byId("login-form-template").textContent;
var template = lang.replace(dialogTemplate, {
form: formTemplate
});
var contentWidget = new (declare(
[_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],
{
templateString: template
}
));
contentWidget.startup();
var content = this.content = contentWidget;
this.form = content.form;
// shortcuts
this.submitButton = content.submitButton;
this.cancelButton = content.cancelButton;
this.messageNode = content.messageNode;
},
postCreate: function() {
this.inherited(arguments);
this.readyState= this.READY;
this.okLabel = this.submitButton.get("label");
this.connect(this.submitButton, "onClick", "onSubmit");
this.connect(this.cancelButton, "onClick", "onCancel");
this.watch("readyState", lang.hitch(this, "_onReadyStateChange"));
this.form.watch("state", lang.hitch(this, "_onValidStateChange"));
this._onValidStateChange();
},
onSubmit: function() {
this.set("readyState", this.BUSY);
this.set("message", "");
var data = this.form.get("value");
// ask the controller to login
var auth = this.controller.login(data);
Deferred.when(auth, lang.hitch(this, function(loginSuccess) {
if (loginSuccess === true) {
this.onLoginSuccess();
return;
}
this.onLoginError();
}));
},
onLoginSuccess: function() {
this.set("readyState", this.READY);
this.emit("success");
},
onLoginError: function() {
this.set("readyState", this.READY);
this.set("message", "Please try again.");
this.emit("error");
},
onCancel: function() {
this.emit("cancel");
},
_onValidStateChange: function() {
this.submitButton.set("disabled", !!this.form.get("state").length);
},
_onReadyStateChange: function() {
var isBusy = this.get("readyState") == this.BUSY;
this.submitButton.set("label", isBusy ? this.busyLabel : this.okLabel);
this.submitButton.set("disabled", isBusy);
}
});
Please see templates at the aforementioned jsFiddle. They should be in separate files required
via dojo/text!
normally. I put them into <script type="text/template">
to fit into jsFiddle.
请参阅上述jsFiddle 中的模板。他们应该在单独的文件required
通过dojo/text!
正常。我将它们放入<script type="text/template">
以适应 jsFiddle。
回答by mschr
Seing as you template the widget, you would want to make use of the templated widget parse. Taken from http://dojotoolkit.org/documentation/tutorials/1.6/templated/below describes how to attach an event to a simple domnode.
在为小部件模板化时,您可能希望使用模板化小部件解析。摘自http://dojotoolkit.org/documentation/tutorials/1.6/templated/下面描述了如何将事件附加到一个简单的 domnode。
<div
data-dojo-attach-point="focusNode"
data-dojo-attach-event="ondijitclick:_onClick"
role="menuitem" tabindex="-1">
<span data-dojo-attach-point="containerNode"></span>
</div>
Seing as you have widgets in template, make references to your child-widgets and set their properties through these references.
看到模板中有小部件,请引用您的子小部件并通过这些引用设置它们的属性。
<td align="center" valign="top">
<button
id="LoginButton" type="submit"
dojoType="dijit.form.Button"
dojoAttachPoint="submitButtonNode">
Ok
</button>
</td>
Create a folder so it becomes 'sibling' to dijit/dojox/dojo folders, call it 'app'. And following widget declaration, put in a file called app/widget/MyWidget.js under;
创建一个文件夹,使其成为 dijit/dojox/dojo 文件夹的“兄弟”,将其命名为“app”。并在widget声明之后,放入一个名为app/widget/MyWidget.js的文件下;
define([
"dojo/_base/declare",
"dijit/_Widget",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/text!app/views/Login/Login.html",
"dijit/Dialog",
"dijit/form/Button",
"dijit/form/TextBox"
], function(
declare,
_Widget,
_TemplatedMixin,
_WidgetsInTemplateMixin,
template,
Dialog
){
return declare("app.widget.MyWidget", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin, Dialog], {
templateString: template
postCreate: function() {
this.inherited(arguments);
// make reference to widget from the node attachment
this.submitButton = dijit.getEnclosingWidget(dojo.query(".dijitButton")[0], this.domNode);
// or simply dijit.byId('LoginButton');
// override its onSubmit
this.submitButton.onClick = function(){
alert("username :" + dom.byId("userId").value()
+ " Password: " + dom.byId("password").value());
};
},
// and a sample on how to implement widget-in-template stateful get/setter pattern
// e.g. if submitbutton label should change on some event, call as such:
// dijit.byId('loginForm').set("submitLabel", "Sendin login, please wait");
_setSubmitLabelAttr : function(value) {
return this.submitButton.set("label", value);
},
_getSubmitLabelAttr : function() {
return this.submitButton.get("label");
}
});
});
And once files are in place, write your html like so:
一旦文件就位,像这样写你的html:
<head>
<script src=...dojo...></script>
<script>
dojo.require([
"dojo/parser",
"app/widget/MyWidget",
"dojo/domReady!" ] , function(parser) {
parser.parse();
});
</script>
</head>
<body>
<form dojoType="app.widget.MyWidget"></div>
</body>
This will do following:
这将执行以下操作:
- load the dojotoolkit (dojo/dojo.js)
- create a namespace called 'app' which has a subspace 'widget'
- render body (the simple form dom node)
- call script ondomready, requireing
app.widget.MyWidget
- MyWidget requires the dependencies
- parser.parse instantiates the
<form dojoType="mywidget">
- 加载 dojotoolkit (dojo/dojo.js)
- 创建一个名为“app”的命名空间,它有一个子空间“widget”
- 渲染体(简单形式的 dom 节点)
- 调用脚本 ondomready,需要
app.widget.MyWidget
- MyWidget 需要依赖项
- parser.parse 实例化
<form dojoType="mywidget">
回答by fneron
With the help of mschr. I came accross this particular solution.
在 mschr 的帮助下。我遇到了这个特殊的解决方案。
define([
"dojo/_base/declare",
"dojo/dom",
"dijit/_Widget",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/text!app/views/Login/Login.html",
"dijit/Dialog",
"dijit/form/Button",
"dijit/form/TextBox"
], function(
declare,
dom,
_Widget,
_TemplatedMixin,
_WidgetsInTemplateMixin,
template,
Dialog
){
return declare([_Widget, _TemplatedMixin, _WidgetsInTemplateMixin, Dialog], {
templateString: template,
postCreate: function() {
this.inherited(arguments);
// make reference to widget from the node attachment
//this.submitButton = this.getChildren()[ButtonIndex];
// override its onSubmit
/*alert("username :" + dom.byId("userId").value()
+ " Password: " + dom.byId("password").value());*/
dojo.connect(this.loginButton, 'onclick', this._login);
},
// and a sample on how to implement widget-in-template stateful get/setter pattern
// e.g. if submitbutton label should change on some event, call as such:
// dijit.byId('loginForm').set("submitLabel", "Sendin login, please wait");
_login : function() {
var value = dom.byId("userId").value;
if(value)
alert("username: " + value);
},
// and a sample on how to implement widget-in-template stateful get/setter pattern
// e.g. if submitbutton label should change on some event, call as such:
// dijit.byId('loginForm').set("submitLabel", "Sendin login, please wait");
_setSubmitLabelAttr : function(value) {
return this.submitButton.set("label", value);
},
_getSubmitLabelAttr : function() {
return this.submitButton.get("label");
},
});
});