Task: show hide a message with some result.

Solution : implemented through custom bindings , got quite a lot of code.

function MyViewModel() { var self = this; self.state = ko.observable(false); self.message = ko.observable(''); self.save = function() { self.state(true); self.message("Result of saving " + new Date()); }; // ko.bindingHandlers.slideVisible = { init: function(element, valueAccessor) { var value = ko.unwrap(valueAccessor()); $(element).toggle(value); }, update: function(element, valueAccessor, allBindings) { var value = ko.unwrap(valueAccessor()), duration = allBindings.get("slideDuration") || 400, delay = allBindings.get("slideDelay") || 2000; if (value) { $(element).slideDown(duration); setTimeout(function() { $(element).slideUp(duration, function() { self.state(false); self.message(''); }); }, delay); } } }; } // ko.applyBindings(new MyViewModel()); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <button class="btn btn-default" data-bind="click: save, disable:state">Save</button> <br> <div class="alert alert-success" data-bind="slideVisible: state, text: message"></div> 

JSFiddle example

Question: Is there any more correct and elegant way to implement similar functionality on Knockout.js? Confuses a large amount of code for such a simple task.

    1 answer 1

    It is not necessary to use the knockout.js markup everywhere. All sorts of dialogues are much more convenient to call imperatively, rather than “forwarding” the display logic through the MVVM pattern.

    Try this:

     function showMessage(options) { var duration = 'duration' in options ? options.duration : 400; var delay = 'delay' in options ? options.delay : 2000; var $div = $('<div>').html($('#messageDialogTemplate').html()).appendTo(document.body); ko.applyBindings(options, div[0]); return $div.slideDown(duration).then(function() { return $.delay(delay); }).then(function() { return $div.slideUp(duration); }).always(function() { ko.cleanNode($div[0]); $div.remove(); }) } 
    • Pavel Mayorov, could you write your example in JSFiddle? I suspect that they did not test. Thank. - pavelchervov
    • @pavelchervov no, I can not. But if you have any errors, I can look at them. - Pavel Mayorov