I have an HTML:
<div class="inter">
<!-- ko if:emprel_id -->
<!-- ko i18n:'dependents.editDependent' --><!-- /ko -->
<!-- /ko -->
<!-- ko if:emprel_id -->
<!-- ko i18n:'dependents.DependentInformation' --><!-- /ko -->
<!-- /ko -->
</div>
The snippets of the JS file "en-CA" is:
"dependents.editDependent": "Edit",
"dependents.DependentInformation": "Dependent Information",
At this moment, at the front-end I am able to see the following in Desktop view:
My task is:
After 767 pixels screen size, I want only "Edit" to show up in place of "Edit Dependent Information"
Also, in between 320 pixels and 767 pixels(which is the mobile view), I want only "Dependent Information"
I can achieve this thorugh HTML and CSS but I am wondering how I can achieve it through JS(knockout).
You could use matchMedia
to keep an observable
state up to date. Then, you can use this state in a computed property that either translates the text, or hides an element from the DOM.
In this example I'm doing two things: (To test, press Full page and resize)
isSmall
, isMedium
and isLarge
In the code, you can see two approaches:
The viewmodel holds, in both cases, the logic that transforms from specific state to specific string combination.
// Keep track of state
var small = window.matchMedia("(max-width: 320px)");
var medium = window.matchMedia("(min-width: 321px) and (max-width: 768px)");
var large = window.matchMedia("(min-width: 769px)");
var isSmall = ko.observable(small.matches);
var isMedium = ko.observable(medium.matches);
var isLarge = ko.observable(large.matches);
var onChange = function() {
isSmall(small.matches);
isMedium(medium.matches);
isLarge(large.matches);
}
small.addListener(onChange);
medium.addListener(onChange);
large.addListener(onChange);
// VM
function ViewModel() {
// For option 1
this.translatedLabel = ko.pureComputed(function() {
if (isSmall()) return i18nextko.t("dependents.editDependent");
if (isMedium()) return i18nextko.t("dependents.DependentInformation");
if (isLarge()) return i18nextko.t("dependents.editDependent") +
" " + i18nextko.t("dependents.DependentInformation");
}, this);
// For option 2
this.showLeft = ko.pureComputed(function() {
return !isMedium();
}, this);
this.showRight = ko.pureComputed(function() {
return !isSmall();
}, this);
}
// Mock
var i18nextko = {
t: function(key) {
switch (key) {
case "dependents.editDependent":
return "Edit";
case "dependents.DependentInformation":
return "Dependent Information";
}
}
};
ko.bindingHandlers.i18n = {
init: function(e, valueAccessor) {
e.innerText = i18nextko.t(valueAccessor());
},
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h2>Via computed</h2>
<div data-bind="text: translatedLabel"></div>
<h2>Via visible binding</h2>
<span data-bind="i18n: 'dependents.editDependent', visible: showLeft"></span>
<span data-bind="i18n: 'dependents.DependentInformation', visible: showRight"></span>
I'm curious to know why you'd rather do it in javascript than in HTML + CSS though...