Отслеживание изменений в свойствах Js объекта с использованием dirtyFlag из пакета KoLite

в 11:26, , рубрики: javascript, knockout, Веб-разработка, разработка, метки: ,

Отслеживание изменений в свойствах Js объекта с использованием dirtyFlag из пакета KoLite
Для отслеживания изменений, в объекте ViewModel, может помочь dirtyFlag, входящий в состав библиотеки KoLite, которая в свою очередь расширяет возможности knockout, добавляя новые возможности:

  • dirtyFlag — предназначен для отслеживания изменений как в отдельных, так и в совокупности свойств ViewModel
  • asyncCommand — предназначается для выполнения асинхронных команд
  • activity — предназначена для индикации активности. Используется совместно с asyncCommand

Описание

Пакет библиотеки расширения knockout написали два человека: Hans Fjällemark и John Papa
Посмотреть исходные коды и примеры можно тут.

Пример использования dirtyFlag для детектирования изменений в объекте ViewModel

Для примера возьмем вот такой объект ViewModel:

 function Vm(){
        var user = {
            name : ko.observable('Alexey'),
            email : ko.observable('alexey@mail.me'),
            address : ko.observable('Moskow st. Petrov 12'),
            awards : ko.observableArray([new Award('silver','The best speaker'), new Award('gold','Brain Storm #2')])
        },
        dirtyFlag = ko.DirtyFlag(user);
        return {
            user : user,
            dirtyFlag : dirtyFlag,
            modelStatus : ko.computed(function(){
                return dirtyFlag().isDirty() ? "Changes detected" : "No changes";
            }),
            clearDirty : function(){
                dirtyFlag().reset();             
            }
        }
    };

В данной ViewModel используется свойство dirtyFlag, которое будет отслеживать изменения значений внутри составного свойства user. Для того чтобы указать что именно на свойстве user будет производиться трекинг, используется конструкция вида: ko.DirtyFlag(user);. После биндинга модели, dirtyFlag будет отслеживать изменения в свойстве user. Для того чтобы получить статус «загрязненности» данных нужно вызвать dirtyFlag().isDirty(). isDirty() возвращает true если обнаружены изменения и false в противном случае. Если пользователь произвел изменения, а затем вернул данные в первоначальное состояние, то isDirty вернет false, так как сохраняет первоначальное состояние анализируемых свойств.

Ниже привожу полный код примера, в котором можно убедиться в возможностях dirtyFlag.

HTML код примера

<div class ="userform" data-bind="with: user">
    <h4>Test user information</h4>
    <label>Name</label>
    <input type="text" data-bind="value: name"/>
    <label>E-mail</label>
    <input type="text" data-bind="value: email"/>
    <label>Address</label>
    <input type="text" data-bind="value: address"/>
    <div class="awards-title">
        <h4>Awards:</h4>
    </div>
    <div class="userAwardForm" data-bind="foreach: awards">
        <div class="userAwardForm">
            <label>Type of award:</label>
            <input type="text" data-bind="value: awardType">
            <label>Name of Contest</label>
            <input type="text" data-bind="value: contestName">
        </div>
    </div>
</div>
<div class="dirty-status">
    <span>Dirty status:   </span><a href="#" data-bind="text: modelStatus(), css: {ok : !dirtyFlag().isDirty(), nok : dirtyFlag().isDirty()}"  class="modern"></a>
</div>

<input type="button" class="Button" value="Reset dirty status" data-bind="click: clearDirty">

JavaScript код примера

$(function() {
    function Award(atp, contestNamev){
        var awardType = ko.observable(atp),
            contestName = ko.observable(contestNamev);
        return {
            awardType : awardType,
            contestName : contestName
        }
    }
            
    function Vm(){
        var user = {
            name : ko.observable('Alexey'),
            email : ko.observable('alexey@mail.me'),
            address : ko.observable('Moskow st. Petrov 12'),
            awards : ko.observableArray([new Award('silver','The best speaker'), new Award('gold','Brain Storm #2')])
        },
        dirtyFlag = ko.DirtyFlag(user);
        return {
            user : user,
            dirtyFlag : dirtyFlag,
            modelStatus : ko.computed(function(){
                return dirtyFlag().isDirty() ? "Changes detected" : "No changes";
            }),
            clearDirty : function(){
                dirtyFlag().reset();             
            }
        }
    };
  
    ko.applyBindings(new Vm());
});​

CSS код примера
body{
    background-color: #456192 ;
    margin:20px;
}

label{
    display:block;
    color: white;
}
div.userform, div.userAwardForm{
   padding: 10px;
   border: solid white 1px;
}

div.userAwardForm{
    margin-top: 10px;
}

div.userform h4{
    font-weight : bold;
    font-size:24px;
    margin-bottom: 15px;
    color: white;
}

.awards-title{
    margin-top:10px;
}

.modern {
    height: 40px;
    padding: 0 5px;
    line-height: 40px;
    font-size: 14px;
    font-weight: bold;
    color: white;
    text-shadow: -1px -1px 0 #333;
    border-radius: 3px;
    text-decoration:none;
}
.ok{
     background: -moz-linear-gradient(#84AB69, #334823);
    background: -webkit-linear-gradient(#84AB69, #334823);
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#84AB69', endColorstr='#334823')";
}

.nok{
     background: -moz-linear-gradient(#ED3812, #7A1F05);
    background: -webkit-linear-gradient(#ED3812, #7A1F05);
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ED3812', endColorstr='#7A1F05')";
}

.dirty-status{
    height: 50px;
}

.dirty-status span{
    color: white;
}

.Button
{
    position: relative;
    cursor: pointer;
    display: inline-block;
    border: 1px solid #d5d5d5;
    text-decoration: none;
    font: 16px Arial;
    font-weight: bold;
    text-align: center;
    text-shadow:0px 0px 0px #444444;
    background: #ffffff;
    padding: 10px 16px;
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    border-radius: 10px;
    color: #c13737;
    -moz-box-shadow:inset 0px 0px 0px;
    -webkit-box-shadow:inset 0px 0px 0px;
    box-shadow:inset 0px 0px 0px,
    0 3px 0 #aeaeae,
    0 5px 0 #c13737,
    0 8px 0 #aeaeae,
    0 10px 6px rgba(0,0,0, .60);
}

.Button:hover {
    background: #eeeeee;
    color: #eb5e7f;
    -moz-box-shadow:inset 0px 0px 0px;
    -webkit-box-shadow:inset 0px 0px 0px;
    box-shadow:inset 0px 0px 0px ,
    0 3px 0 rgba(235,94,127, .30),
    0 3px 0 #aeaeae,
    0 5px 5px #eb5e7f,
    0 5px 0 #eb5e7f,
    0 8px 0 rgba(235,94,127, .15),
    0 8px 0 #aeaeae,
    0 10px 6px rgba(0,0,0, .60);
}

.Button:active {
    transform: translateY(2px);
    -moz-transform: translateY(2px);
    -ms-transform: translateY(2px);
    -o-transform: translateY(2px);
    -webkit-transform: translateY(2px);
    -moz-box-shadow:inset 0px 0px 0px;
    -webkit-box-shadow:inset 0px 0px 0px;
    box-shadow:inset 0px 0px 0px,
    0 3px 0 rgba(235,94,127, .30),
    0 3px 0 #eeeeee,
    0 5px 5px rgba(#eb5e7f, .65),
    0 5px 0 #eb5e7f,
    0 6px 0 rgba(235,94,127, .15),
    0 6px 0 #eeeeee,
    0 6px 6px rgba(0,0,0, .65);
}

В примере, в качестве индикации выводятся надписи: «No changes» — если изменения не обнаружены и «Changes detected» — если изменения найдены. А так же производится изменение фона на котором выводятся надписи для индикации.

На форме примера расположена кнопка«Reset dirty status», которая и производит демонстрацию работы метода reset у свойства dirtyFlag ViewModel. Для того чтобы текущие изменения были приняты, как базовые, нужно произвести вызов dirtyFlag().reset();.

Заключение

Думаю что данная библиотека поможет с легкостью отслеживать изменения на необходимых свойствах ViewModel.

Спасибо за внимание!

P.S. Картинку к посту нарисовал сам :)

Автор: CyberLight

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js