Knockout: HTML-binding in text-binding - html

Depending on the outcome of an expression in my text data-binding,
I would like to display a property or some HTML code.
This is the expression:
resultsCount().length > 0 ? resultsCount().length : {html: loadingIcon}
And it's being used in the following context:
<span data-bind="text: resultsCount().length > 0 ? resultsCount().length : {html: loadingIcon}"></span></strong></p>
This obviously doesn't work (because of {html: loadingIcon}), but I'd like to know how I can make this work.
The loadingIcon HTML is a simple HTML structure like this:
self.loadingIcon = "<div class='loadingIconWrapper'><i class='glyphicon glyphicon-refresh'></i></div>";
How can I achieve this? Thanks in advance.

You can use just html binding to achieve result.
<span data-bind="html: resultsCount().length > 0 ? resultsCount().length :loadingIcon"></span>
Fiddle demo
Or if you don't want to use html binding for displaying number then use if binding.
<!-- ko if: resultsCount().length> 0 -->
<span data-bind="text:resultsCount().length"></span>
<!-- /ko -->
<!-- ko ifnot: resultsCount().length> 0 -->
<span data-bind="html:loadingIcon"></span>
<!-- /ko -->
Fiddle demo

Related

KnockOut.js in HTML <!-- ko if: $root.valueA || $root.valueB --> NOT Working with OR '||'

I want to show a HTML paragraph based on a condition. This is working when I have only one. But, is now working when I use || operand.
Any help would be appreciated.
New to js - forgive if I am missing something.
<!-- ko if: $root.valueA || $root.valueB -->
<p>
Show this message.
</p>
<!-- /ko -->
Assuming valueA and valueB are observables, you need to manually unwrap them:
<!-- ko if: $root.valueA() || $root.valueB() -->

How do I prevent <span> element from getting created if certain property in $root is null?

I display some text in a <span> element which looks like this
<span data-bind="text: $root.participants()[_propkey].Currency"></span>
When root.participants()[_propkey].Currency is null, I get an empty space on page.
How do I prevent this span from getting created if root.participants()[_propkey].Currency is null
you can use virtual elements and the if binding to achieve what you're after
var vm = {
Currency : ko.observable()
};
ko.applyBindings(vm);
span {background-color: cornflowerblue}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
Currency span
<!-- ko if: Currency -->
<span data-bind="text: Currency"></span>
<!-- /ko -->
is here
<br />
Test: <input data-bind="textInput: Currency">

knockoutjs if statement and replace text with html

what would be the best way to aproach this in knockoutjs?
I want to replace the data-bind="text: Order" with an image based on what is returned. Examples of what ive tried are in the code below. First example works ok but just returns text (ASC or DESC). 2nd example just returns both. Third example works but I need to display the object as html. Thanks.
<div class="col-md-3 sort-order">
<!--<div class="col-md-3 sort-field" data-bind="text: Order"></div>-->
<!-- ko if: Order() === 'ASC' -->
<object data='~/Content/svg/plans/order-down.svg' type='image/svg+xml' />
<!-- /ko -->
<!-- ko if: Order() === 'DESC' -->
<object data='~/Content/svg/plans/order-up.svg' type='image/svg+xml' />
<!-- /ko -->
</div>
<!--<div class="col-md-3 sort-order" data-bind="text: (ko.unwrap(Order) == 'ASC') ?'<object data='~/Content/svg/plans/order-down.svg' type='image/svg+xml' />' : '<object data='~/Content/svg/plans/order-up.svg' type='image/svg+xml' />'">
</div>-->
In your code instead of using the text binding use like this:
data-bind="html:'your html part goes here'"

Conditional "With" binding on data-bind

Using knockout JS, how can I apply a conditional with binding to HTML?
I have two observables, either one should be used based on a condition for the same html code. I want to do something like this:
if some-condition:
<div data-bind="with: observable1">
else:
<div data-bind="with: observable2">
<!-- the below is common code -->
<label data-bind: "text: observable-property"></label>
<!-- .... -->
</div>
<div data-bind="with: var1() ? var2 : var3">
<div data-bind="text: a">
</div>
</div>
You can bind an observable conditionally to the with binding like this.
See this fiddle for a demo.
You could use comment tags:
<!-- ko if: foo -->
<div data-bind="with: bar"></div>
<!-- /ko -->
<!-- ko ifnot: foo -->
<div data-bind="with: baz"></div>
<!-- /ko -->

Go - HTML comments are not rendered

I'm building go web application. I found some anomaly on the rendered html page. All of my html comments <!-- --> are suddenly not being rendered. My guess it's because the go version I used (just updated to higher version), because it was fine before I updated it.
This is my code:
<!-- prepare the breadcrumbs -->
<ul class="breadcrumb" data-bind="foreach: viewModel.breadcrumbs">
<!-- ko if: ($index() + 1) < len(viewModel.breadcrumbs()) -->
<li>
<a data-bind="attr: { href: href }">
<i class="fa fa-home"></i>
<span data-bind="text: title"></span>
</a>
</li>
<!-- /ko -->
<!-- ko if: ($index() + 1) == len(viewModel.breadcrumbs()) -->
<li class="active" data-bind="text: title"></li>
<!-- /ko -->
</ul>
And this is the rendered page source:
Because of this issue, many of my KnockoutJS codes which are written using containerless control flow syntax goes crazy, it doesn't work at all.
What should I do to solve this? Thanks in advance
There is a special type in the html/template package: template.HTML. Values of this type in the template are not escaped when the template is rendered.
So you may "mark" your HTML comments as template.HTML and so they will not be escaped or omitted during executing your template.
One way to do this is to register a custom function for your template, a function which can be called from your template which takes a string argument and returns it as template.HTML. You can "pass" all the HTML comments to this function, and as a result, your HTML comments will be retained in the output.
See this example:
func main() {
t := template.Must(template.New("").Funcs(template.FuncMap{
"safe": func(s string) template.HTML { return template.HTML(s) },
}).Parse(src))
t.Execute(os.Stdout, nil)
}
const src = `<html><body>
{{safe "<!-- This is a comment -->"}}
<div>Some <b>HTML</b> content</div>
</body></html>`
Output (try it on the Go Playground):
<html><body>
<!-- This is a comment -->
<div>Some <b>HTML</b> content</div>
</body></html>
So basically after registering our safe() function, transform all your HTML comments to a template action calling this safe() function and passing your original HTML comment.
Convert this:
<!-- Some HTML comment -->
To this:
{{safe "<!-- Some HTML comment -->"}}
Or alternatively (whichever you like):
{{"<!-- Some HTML comment -->" | safe}}
And you're good to go.
Note: If your HTML comment contains quotation marks ('"'), you can / have to escape it like this:
{{safe "<!-- Some \"HTML\" comment -->"}}
Note #2: Be aware that you shouldn't use conditional HTML comments as that may break the context sensitive escaping of html/template package. For details read this.
You can use text/template instead of html/template and do all escaping manually using built-in functions such as html and js (https://golang.org/pkg/text/template/#hdr-Functions). Be aware that this is very error prone though.