Question

We are developing a desktop application using a HTML frontend (mostly a view) and a python backend (mostly a document).

The document is updated by using input elements. The view is updated calling updateView function (open document, undo/redo, gizmos...).

So, we need to notify the document when the user types something. Changes are detected by subscribing to observables and calling updateDocument.

The main problem is we don't need to notify the document if view is updated directly by the backend.

How can we update the view using updateView without notifying the document again ?

View HTML :

<!DOCTYPE html>
<html lang="fr">
    <head>
        <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />

        <script type="text/javascript" src="jsext/jquery-2.0.3.min.js"></script>
        <script type="text/javascript" src="jsext/knockout-2.3.0.js"></script>
        <script type="text/javascript" src="jsext/knockout.mapping.js"></script>

        <script type="text/javascript" src="js/document.js"></script>
        <script type="text/javascript" src="js/view.js"></script>

    </head>

    <body>
        <div id="datas">            
            <div>
                <p>
                    <label>x : </label>
                    <input type="text" data-bind="value: x"/>
                </p>
                <p>
                    <label>y : </label>
                    <input type="text" data-bind="value: y"/>
                </p>
                <p>
                    <label>z : </label>
                    <input type="text" data-bind="value: z"/>
                </p>
                <p>
                    <label>rx : </label>
                    <input type="text" data-bind="value: rx"/>
                </p>
                <p>
                    <label>ry : </label>
                    <input type="text" data-bind="value: ry"/>
                </p>
                <p>
                    <label>rz : </label>
                    <input type="text" data-bind="value: rz"/>
                </p>
                <p>
                    <label>s : </label>
                    <input type="text" data-bind="value: s"/>
                </p>
            </div>
        </div>
    </body>
</html>

View JS :

var _viewModel;
var subscriptions = [];

$(document).ready(function(){
    _viewModel = new Transform( );
    ko.applyBindings( _viewModel );
} );

function makeObservable() {
    var ob = ko.observable( 0.0 );
    ob.subscribe( function (val) {
        updateDocument( ko.toJSON( _viewModel ) );
    });
    return ob;
}

function Transform() {
    this.__type__ = makeObservable();
    this.x = makeObservable();
    this.y = makeObservable();
    this.z = makeObservable();
    this.rx = makeObservable();
    this.ry = makeObservable();
    this.rz = makeObservable();
    this.s = makeObservable();
}

function updateView( jsonDocument ){
    var jsonDocument = JSON.parse( jsonDocument );           
    _viewModel.x( jsonDocument[ "x" ] );
    _viewModel.y( jsonDocument[ "y" ] );
    _viewModel.z( jsonDocument[ "z" ] );
    _viewModel.rx( jsonDocument[ "rx" ] );
    _viewModel.ry( jsonDocument[ "ry" ] );
    _viewModel.rz( jsonDocument[ "rz" ] );
    _viewModel.s( jsonDocument[ "s" ] );
    _viewModel.__type__( jsonDocument[ "__type__" ] );
}

Thanks

Was it helpful?

Solution

You could add a field named silentUpdate to disable event hendler.

function makeObservable() {
    var ob = ko.observable( 0.0 );
    ob.subscribe( function (val) {
        if(_viewModel.silentUpdate) return;
        updateDocument( ko.toJSON( _viewModel ) );
    });
    return ob;
}


function Transform() {
    this.silentUpdate = false;
    ...
}

function updateView( jsonDocument ){
    _viewModel.silentUpdate = true;
    var jsonDocument = JSON.parse( jsonDocument );           
    _viewModel.x( jsonDocument[ "x" ] );
    ...
    _viewModel.__type__( jsonDocument[ "__type__" ] );
    _viewModel.silentUpdate = false;
}

I hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top