Jason
Jason

Reputation: 600

Show default value when Knockout observable undefined or JS disabled

Using Knockout.js, is there a way to have an element's original content show if the observable bound to it is undefined?

<p data-bind="text: message">Show this text if message is undefined.</p>

<script>
    function ViewModel() {
        var self = this;        
        self.message = ko.observable();    
    };

    ko.applyBindings(new ViewModel());
</script>

I know there are workarounds using visible, hidden or if but I find those too messy; I don't want the same element written out twice, once for each condition.

Also, I don't want to use any sort of default observable values. Going that route, if JS is disabled then nothing shows up. Same for crawlers: they would see nothing but an empty <p> tag.

To summarize, I want to say "Show this message if it exists, otherwise leave the element and its text alone."

The reasoning behind this is that I want to first populate my element using Razor.

<p data-bind="text: message">@Model.Message</p>

And then, in the browser, if JS is enabled, I can do with it as I please. If, however, there is no JS or the user is a crawler, they see, at minimum, the default value supplied server side via Razor.

Upvotes: 2

Views: 788

Answers (3)

manji
manji

Reputation: 47978

You can simply use the || operator to show a default message in case message is undefined. Plus put the default text as content:

<p data-bind="text: message() || '@Model.Message' ">@Model.Message</p>

If javascript is disabled, the binding will be ignored and you will have the content displayed instead.

JSFiddle

Upvotes: 6

Tanner
Tanner

Reputation: 22743

You can set a default value like that in a number of ways, simplest way is to set the default observable value, as your JS file will be incorporated in to your HTML and will be able to access @Model.Message, so you can set a default value:

self.message = ko.observable(@Model.Message);

Here are a few other variations:

var viewModel = {
   message: ko.observable(),
   message1: ko.observable('Show this text if message is undefined.')   
};

ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h2>Option 1</h2>
<i>Set default value of observable: self.message1 = ko.observable(@Model.Message);</i>
<p data-bind="text: message1"></p>

<h2>Option 2</h2>
<i>Check for undefined and replace</i>
<p data-bind="text: message() ? message : message1"></p>

<h2>Option 3</h2>
<i>Use KO if syntax to display content if defined/undefined</i>
<!-- ko if: message() -->
<p data-bind="text: message"></p>
<!-- /ko -->

<!-- ko ifnot: message() -->
<p data-bind="text: message1"></p>
<!-- /ko -->

Upvotes: 0

Hari Darshan
Hari Darshan

Reputation: 1920

Try this out

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

<script>
    function ViewModel() {
        var self = this;        
        self.text = ko.observable();    
        self.message = ko.computed(function(){
            if(self.text() != undefined){
                return self.text();
            }else{
                return "Show this text if message is undefined.";
            }
        });
    };

    ko.applyBindings(new ViewModel());
</script>

Upvotes: 0

Related Questions