3

Given this HTML:

<h2 data-bind="text: title"></h2>

<p data-bind="text: summary"></p>

Is there a simple/clean way I can make elements flash if their value is changed?

For example, if I do a web request in the background and update the model with the mapping plugin (which may update all, some, or none of the values). The goal is to make it clearer to the user which elements actually did change, since just the text-change by itself happens so fast.


I'm thinking some sort of data-bind="afterValueChanged" with handler(element, oldValue, newValue), or something along those lines. So I could do:

<div data-bind="afterValueChanged: myHandler">
    ...

And then apply the flash animation in that function somehow... or something... been trying to google, but only finding answers related to changing of input values and such, and in my case there isn't necessarily any input at all.

Svish
  • 152,914
  • 173
  • 462
  • 620
  • There are a few pieces of code that work in another thread. http://stackoverflow.com/questions/1605698/text-blinking-jquery There are two that nice ones near the top that don't require a plugin. – Wes Mar 15 '17 at 22:03

2 Answers2

1

just used a custom binding that does a fade out followed by fade in. change the value in textbox and hit tab.

ko.bindingHandlers.flashingtext = {
  update: function(element, valueAccessor, allBindings) {
    // First get the latest data that we're bound to
    var value = valueAccessor();
    var valueUnwrapped = ko.unwrap(value);
    // Now manipulate the DOM element
    $(element).text(valueUnwrapped);
    $(element).fadeOut("slow", function() {
      $(element).fadeIn("slow", function() {});
    });
  }
};

function model() {
  var self = this;
  this.title = ko.observable('my title');
}

var mymodel = new model();

$(document).ready(function() {
  ko.applyBindings(mymodel);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<h2 data-bind="flashingtext: title"></h2>
change the title: <input type="text" data-bind="value: title">
Bryan Dellinger
  • 4,724
  • 7
  • 33
  • 79
0

A simple trick you could use is exploiting a virtual element with a with binding as such:

HTML:

<!-- ko with: title -->
<h2 data-bind="text: $data"></h2>
<!-- /ko -->

<!-- ko with: summary -->
<h2 data-bind="text: $data"></h2>
<!-- /ko -->

<button type="button" data-bind="click: change">
  Change
</button>

JS:

function viewModel() {
  var self = this;

  this.title = ko.observable('0');
  this.summary = ko.observable('0');

  this.change = function() {
    self.title(Math.random().toString());

    if (self.title() < 0.5) {
      self.summary(Math.random().toString());
    } else {
      self.summary(self.summary());
    }
  }
};

var vm = new viewModel();

ko.applyBindings(vm);

CSS:

h2, p {
  animation: bg 1s backwards;
}

@keyframes bg {
  0% {
    background: #00ff40;
  }
  100% {
    background: initial;
  }
}

Complete fiddle

Let's see how it works (this is just a simplified example since you didn't include any additional code):

By wrapping the h2 and p elements in one-one virtual element to which we apply the with binding, not the contents of the respective elements (h2 and p), but the whole elements themselves (that is, the p and h2 tags in between the comments) get re-rendered whenever the values to which the wrapping virtual elements are bound change.

Since the CSS animation defined is played as soon as the elements to which they apply get (re)created, and because the animation is not repeated, the background of the elements fade from some bright color of your liking into the final background of your choice. (Note that IE might have problems with initial (see this link), just use the color of your preference in place of it.)

For your convenience, I've added some randomness to the code I've provided. You can see, by clicking enough, that should the value of title (excuse me for it being a number, wanted to make it as simple as possible) be less than 0.5, the value of summary is changed, in which case the background color is animated. If title >= 0.5, then the value of summary is not changed - therefore the element is not re-rendered and the animation is not replayed (actually it is changed to the exact same value - I've included it so you can see that even if you pass a value that happens to be the same then no change is fired by knockout).

The downside is that the binding is a little bit dirty because of binding the text content using $data as value, but if you use it in simple scenarios only it might be a useful timesaver.

Balázs
  • 2,929
  • 2
  • 19
  • 34