Реализовать пользовательское сообщение о загрузке 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;

});

person talles_jp    schedule 28.11.2014    source источник


Ответы (2)


На первый взгляд ваш подход здравый, но ваш подход к модулям в 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 в круглых скобках. Это выполняет немедленную оценку, используя значение по умолчанию, предоставленное наблюдаемому, а затем повторно оценивает, когда наблюдаемое изменяется.

Также может потребоваться изменить "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 -- вы переопределяете сам наблюдаемый объект и превращаете его в ненаблюдаемый скаляр. Таким образом, когда значение впоследствии изменяется (с false на true и на false), представление не обновляется.

Также обратите внимание, что вы должны импортировать KnockoutJS.

Еще одна проблема: у вас есть проблема со ссылкой this в вашей функции #complete. Обратите внимание, что я делаю это в верхней части вашей функции #Ok:

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

а затем в вашей функции #complete я делаю следующее:

_vm.loading(false);

Использование this в вашей функции #complete ссылается на саму функцию #complete, а не на viewModel. Мы должны сохранить ссылку на this вне функции #complete.

Была еще одна проблема: #show не было на прототипе.

person Community    schedule 28.11.2014
comment
когда я открываю сейчас, он показывает загружаемое изображение, как только открывает диалоговое окно. - person talles_jp; 29.11.2014
comment
@talles_jp Пожалуйста, опубликуйте свое представление целиком (HTML) и viewModel (js). То, что вы говорите, говорит мне, что вы каким-то образом инициализируете наблюдаемое loading значением true или что вы не настроили свое представление для разыменования наблюдаемого loading. Мне нужно больше информации. - person ; 29.11.2014

Я использую утилиту под названием Block UI в моем файле JS приложения. Я вызываю ее так, используя настройку Global 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;
 }
person DerfB    schedule 23.02.2015
comment
Раньше я тоже использовал Block UI. Это хороший маленький микро-фреймворк. Но если вы посмотрите на вопрос ОП, вы увидите, что он использует Дюрандаль. Мы не кодируем напрямую $(document).ready() в Durandal. На самом деле ваш код будет лучше всего в обработчике attached модели просмотра shell.js. Ты действительно делаешь этот Дюрандаль? - person ; 24.02.2015