2012-06-11 45 views
3

有没有关于如何实现简单的登录页面/对话框的例子?我一直试图用dojo样板做(请查看我以前的问题:Layout implementation for Dojo MVC)。到目前为止,我已经能够显示我的对话框。但我希望能够获取我的数据,并在点击事件中想要例如(带有他的内容)的警告框。Dojo MVC的简单登录实现

我的观点:

<form action="Login" method="post" validate="true" id="loginForm"> 
    <table width="258"> 
    &nbsp; 
    <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">&nbsp;</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> 
      &nbsp; 
      <td align="left" valign="top"><button dojoType="dijit.form.Button" type="submit" onclick="document.Login.reset()" id="Cancel">Cancel</button></td> 
      &nbsp; 
      <td><button dojoType="dijit.form.Button" type="submit" onclick="showDialog();" id="resetPassword"> Show Dialog </button></td> 
      </tr> 
    </table> 
    &nbsp; 
    </td> 
    </tr> 
    </table> 
</form> 

我的微件模块/类

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 
    }); 
}); 

现在,如果你检查HTML元素ID LoginButton应该在这种情况下,所谓的 “连接” 功能。其中应显示(在警告框中)用户名和密码当前输入。

我在哪里放置我的功能?那种......

connect : function(){ 
    alert("username :" + dom.byId("userId").value() 
+ " Password: " + dom.byId("password").value()); 
    } 

编辑:新的代码

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"); 
     }, 
    }); 
}); 

我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!'); 
    } 
}); 
+0

查看我对[Dojo Dialog with confirmation button]的回答(http://stackoverflow.com/questions/10401512/dojo-dialog-with-confirmation-button/10405938#10405938)和示例[jsFiddle上的代码]( http://jsfiddle.net/phusick/wkydY/)。 – phusick

回答

7

我想补充我的解决方案:http://jsfiddle.net/phusick/tG8Sg/

这是一个有点扭曲因的jsfiddle的约束,但主要原则是相同的,因为我在我的编码使用。

首先,登录过程(或任何其他表单处理)被封装在对话框中,并通过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"))); 
}); 

正如你可以在的jsfiddle看到,有两个模板对话框的模板登录表单模板这是我的LoginDialog构造函数中组装。原因是我通常也会有一个包装类dijit/form/Form做一些超出标准dijit/form/Form验证和数据序列化的魔术,但由于登录很简单,它会在jsFiddle的单个文件中混乱,我摆脱了它。从对话框中分离表单的优点是你可以使用相同的表单(即查看)以及其他地方的所有表单专用代码,例如,在ContentPane。形式是那里只是为了显示和收集数据从用户/,它不应该直接与型号沟通,即网络服务,有用于该目的的控制器

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; 
    } 
}); 

创建的实例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"}); 

并将它传递给LoginDialog构造如上述还没有看到:

var loginDialog = new LoginDialog({ controller: loginController}); 

最后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); 
    }    
}); 

请参阅模板在上述jsFiddle。他们应该通过dojo/text!正常在单独的文件required。我把它们放入<script type="text/template">以适合jsFiddle。

+1

比我的方式更好;) – fneron

+0

谢谢。代码来自我的[基于Dojo 1.7的项目](http://cms.egoworx.com/)我想在GitHub上发布。它是CMS + CMS Admin,基本上是一个基于'dojo/store/JsonRest'和['dgrid'](http://dgrid.io)构建的CRUD应用程序。它还包括一个用Zend Framework编写的RESTful后端,所以我认为它可能很有帮助,因为它不是太简单也不是太复杂的例子,这在Dojo生态系统中是缺少的。如果您有兴趣,我会在发布时通知您。 – phusick

+0

你看到了我的其他帖子...我几乎抓住了关于道场的任何信息。所以是的,我很感兴趣。我有一个非常具体的问题给你。你如何基于dojo构建你的网站?你如何分离你的文件?喜欢你的登录例子。我相信我会创建一个文件:dialog-template.html,login-form-template.html(在app/views/templates之类的东西下),然后处理登录js逻辑(app/views/LoginDialog.js)和一个控制器(应用程序/控制器/ LoginController.js)..和我的index.html调用这两个?合理? – fneron

1

Seing你模板窗口小部件,你会想利用的模板化小部件解析。下面从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> 

由于您在模板中有小部件,因此请引用您的子小部件并通过这些引用设置它们的属性。

<td align="center" valign="top"> 
    <button 
    id="LoginButton" type="submit" 
    dojoType="dijit.form.Button" 
    dojoAttachPoint="submitButtonNode"> 
     Ok 
    </button> 
</td> 

创建一个文件夹,使其成为“兄弟”来的dijit/DojoX中/道场文件夹,把它称为“应用”。并且在下面的小部件声明中,放入一个名为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"); 
     } 
    }); 
}); 

一旦文件已经到位,写你的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> 

这将做到以下几点:

  • 负载dojotoolkit(道场/的dojo.js)
  • 创建一个名为'app'的名称空间,它具有一个子空间'widget'
  • render body(简单形式dom节点)
  • 调用脚本ondomready,requireing app.widget.MyWidget
  • 进myWidget需要依赖
  • parser.parse实例化<form dojoType="mywidget">
+0

我在萤火虫中发现一个错误:“声明Login:mixion#0不是一个可调用的构造函数 – fneron

+0

我希望你的mixin#0不是'...'对不对?:)填充空白回答 – mschr

+0

这个dijit。 getEnclosingWidget(this.submitButtonNode)return me null?我不知道你是否看过dojo样板,但基本上有一个文件main.js,我打电话给我的对话框,检查我的编辑。 – fneron

1

随着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"); 
     }, 
    }); 
}); 
+0

不要使用'dojo.connect',否则你的对话框将不会被垃圾收集,直到你手动断开这个处理程序。同时'_login()'方法不会在你的对话框范围内被调用,所以''this.loginButton'在'_login()'里面不可用,你必须编写'dojo.connect(this.loginButton,“onClick”,lang.hitch(this,“_login”))'使用'this.connect(this.loginButton,“onClick”,“_login”)'代替,'_login()'将在对话框范围内被调用,并且连接会在对话框正在被自动断开破坏 – phusick

+0

另请注意,使用'dom.byId()'会导致你使用对话框作为单例,这可能是o k和一个登录对话框,但是你将无法在整个应用程序中控制DOM节点和dij的id。你不应该在dijit模板中使用'id's,而应该使用'data-dojo-attach-point'。 – phusick