实现自定义加载消息DURANDAL

时间:2014-11-28 00:28:53

标签: javascript knockout.js durandal

您好我有一个durandal应用程序,发送数据为ajax但我不知道如何实现加载指标,这里是代码:

这是加载数据的视图 loadinbox.html

<div class="modal-content messageBox">
    <div class="modal-header">
        <h3>LOGIN</h3>
    </div>
    <div class="modal-body">
       <h3>Entre com suas credenciais.</h3>
       <form data-bind="submit: ok">
           <input type="text" data-bind="value: login" placeholder="CPF"  class="form-control autofocus" />
           <input type="text" data-bind="value: senha" placeholder="Senha" class="form-control autofocus" />
       </form>
    </div>
    <div data-bind="if: $parent.loading">
        <img src="img/loading.gif"/>
    </div>

    <div class="modal-footer">
        <button class="btn btn-success" data-bind="click: ok, active: $parent.loading">Login</button>
    </div>
</div>

这是加载数据的模型 loginBox.js

define(function (require) {
    var dialog = require('plugins/dialog');


    var loading = ko.observable();

    var loginBox = function(){
        this.login = '';
        this.senha = '';
        this.loading = false;
    };


 loginBox.prototype.ok = function () {
     this.loading =true;

     $.ajax({
         type: "post", 
         data: { "LoginForm[cpf]" : this.login, "LoginForm[password]" : this.senha , 'ajax':'login-form' },
         url: localStorage['baseurl']+localStorage['router']+'site/login',
         success: function (data){
             console.log(data);
         },
         error: function (request, status, error){
             console.log(request.status);
             console.log(status);
             console.log(error);
         },
         complete: function (data) {
             alert('hqweuiqhioehqio');
             this.loading =false; 
         }
     });
 };


 loginBox.show = function() {
     return dialog.show(new loginBox());
 };    

 return loginBox;

});

2 个答案:

答案 0 :(得分:1)

从表面上看,你的方法很合理,但你在Durandal中对模块的处理方式有些混乱。例如,您已经两次声明loading,一次作为标量,一次作为可观察对象。

所以,让我们创建一个实例模块(这意味着我们将返回一个构造函数):

loginBox.html (查看)

<div class="modal-content messageBox">
    <div class="modal-header">
        <h3>LOGIN</h3>
    </div>
    <div class="modal-body">
        <h3>Entre com suas credenciais.</h3>
        <form data-bind="submit: ok">
           <input type="text" data-bind="value: login" placeholder="CPF"  class="form-control autofocus" />
           <input type="text" data-bind="value: senha" placeholder="Senha" class="form-control autofocus" />
        </form>
    </div>
    <div data-bind="if: $parent.loading()">
        <img src="img/loading.gif"/>
    </div>

    <div class="modal-footer">
        <button class="btn btn-success" data-bind="click: ok, active: $parent.loading()">
            Login
        </button>
    </div>
</div>

请注意,我将if绑定更改为:

"if: loading()"

用括号引用loading。这将使用提供给observable的默认值执行立即eval,然后在observable更改时执行re-eval。

此外,可能需要将"click: ok, active: $parent.loading()"更改为click: $parent.ok.bind($parent), active: $parent.loading()。输入#ok函数时,使用调试器检查上下文。

逻辑说明:在我看来,你在模态页脚中的意思是

active: !$parent.loading()

表单加载数据时,OK按钮是否真的有效?

loginBox.js(模块实例方法)

define (
    [
        'plugins/dialog',
        'knockout'
    ],
    function (
        dialog,
        ko) {

        var LoginBox = function () {

            this.login = '';
            this.senha = '';
            this.loading = ko.observable(false);
        };

        LoginBox.prototype.ok = function () {
            var _vm = this;

            this.loading(true);

            $.ajax( {
                type: "post", 
                data: { "LoginForm[cpf]" : this.login, "LoginForm[password]" : this.senha , 'ajax':'login-form' },
                url: localStorage['baseurl']+localStorage['router']+'site/login',
                success: function (data) {
                    console.log(data);
                },
                error: function (request, status, error) {
                    console.log(request.status);
                    console.log(status);
                    console.log(error);
                },
                complete: function (data) {
                    alert('hqweuiqhioehqio');
                    _vm.loading(false);
                }
           });
        };

        LoginBox.prototype.show = function() {
            dialog.show(this);
        };  

        return LoginBox;

    };
);

注意我对this.loading的处理。它是一个可观察的,并且使用我在上面显示的方法更新了可观察量(记住,它们是函数)。当您以这种方式分配true - this.loading = true时 - 您将覆盖observable本身并将其转换为不可观察的标量。因此,当值稍后更改(从false变为true)时,视图不会更新。

另请注意,您必须导入KnockoutJS。

另一个问题:您的#complete函数中存在this引用问题。请注意,我在#Ok函数的顶部执行此操作:

var _vm = this;  //Some people are inclined to this format: var that = this;

然后,在#complete函数中,我这样做:

_vm.loading(false);

在#complete函数中使用this引用#complete函数本身,而不是viewModel。我们必须在#complete函数之外保存对this 的引用

还有另一个问题:#show不在原型上。

答案 1 :(得分:0)

我使用名为Block UI的实用程序 在我的App JS文件中,我使用全局Ajax设置调用它。 通过这种方式,您只需执行一次,然后每个Ajax调用将显示您的加载gif并在任何Ajax调用开始和结束时隐藏

<强> HTML: 在index.html页面(您的主页)

  <div id="throbber" style="display:none;">
            <img src="/images/gears.gif" />
        </div>

<强>的Javascript

$(document).ready(function () {    
        $.blockUI.defaults.css.border = 'none';
        $.blockUI.defaults.css.backgroundColor = 'transparent';
        $.blockUI.defaults.message = $('#throbber');
        $.blockUI.defaults.showOverlay = true;
        $.blockUI.defaults.overlayCSS.backgroundColor = "#fff";

        $(document).ajaxStart(function () {
                $.blockUI();            
        }).ajaxStop(function () {
            $.unblockUI();
        });
    });

<强> CSS:

#throbber{
    border:1px solid #346789;
    padding: 15px;
    background-Color: #fff;
    -moz-border-radius:0.5em;
    border-radius:0.7em;
    opacity:0.8;
    filter:alpha(opacity=80);
    color: #000 ;
    width:133px;
    height:133px;
    left: 50%;
    top: 40%;
    position: fixed;
 }