javascript – Knockout.js show and hide message

Question:

Objective: to show and hide the message with some result.

Solution : implemented through custom bindings , it turned out 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>

Example on JSFiddle

Question: is there any more correct and elegant way to implement this functionality in Knockout.js? Confused by the large amount of code for such a simple task.

Answer:

You don't have to use knockout.js markup everywhere. It is much more convenient to call all kinds of dialogs imperatively, and not to "throw" the display logic through the MVVM pattern.

Try it like 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();
  })
}
Scroll to Top