Saturnix
Saturnix

Reputation: 10554

Knockout data-bind syntax in razor

In this simple CSS Knockout binding

<tag data-bind="css: { 'class_1': condition1, 'class_2': condition2 }" />

I'd like to port class_1 and class_2 to C# variables. This is my first attempt:

<tag data-bind="css: { '@class1': condition1, '@class2': condition2 }" />

Other attempts resulted in me having to declare a separate variable containing the binding statement.

string bind = string.Format("'{0}': condition1, '{1}': condition2", class1, class2)
<tag data-bind = "css: { @bind }" />

and, finally:

string bind = string.Format("css: {{ '{0}': condition1, '{1}': condition2 }}", class1, class2)
<tag data-bind = "@bind" />

None of these blocked the rendering of the page but the first two results in Visual Studio indicating a syntax error. I'd like to do this bind:

Is it possible?

The last example, the only one which doesn't give syntax errors, sacrifies code readability, especially for larger statements. Is there any alternative which looks more like my first attempt? Knockout MVC seems a little bit too invasive: is there something similar but which can solve only this issue?

Upvotes: 0

Views: 2297

Answers (3)

Francis
Francis

Reputation: 1244

I've not got VS 2012 installed on my machine any more, but VS 2013's syntax highlighting accepts this code:

<style>
    .myClass {
        color: red;
    }
</style>

@{
    var MyClass = "myClass";
}

<div id="fooId">
    <span data-bind="css: { '@MyClass': enableClass }, text: myText"></span>
</div>

@section scripts{    
    <script>
        var vm = {
            enableClass: ko.observable(true),
            myText: ko.observable('foobarbaz')
        };
        ko.applyBindings(vm, document.getElementById('fooId'));
    </script>
}

Upvotes: 2

Vinney Kelly
Vinney Kelly

Reputation: 5095

@Saturnix, since you said that the class value is only variable from the server, you can--and probably should--keep the class variables out of your KO model. Here's what I'm thinking:

@{ 
var class1 = Model.condition1 ? 'class1' : '';
var class2 = Model.condition2 ? 'class2' : '';
}
<input data-bind="value: myValue" class="@class1 @class2" />

Or, you could simplify your view by modifying the view model to contain class variables directly. Such as:

public class MyViewModel
{
    public bool Condition1 {get; set;}
    public bool Condition2 {get; set;}
    public string Class1 
    {
        get { return Condition1 ? 'class1' : ''; }
    }
    public string Class2
    {
        get { return Condition2 ? 'class2' : ''; }
    }
}

<input data-bind="value: myValue" class="@Model.Class1 @Model.Class2" />

Or even:

public class MyViewModel
{
    public bool Condition1 {get; set;}
    public bool Condition2 {get; set;}
    public string classes 
    {
        get 
        { 
            var classes = new List<string>();
            if (Condition1) classes.Add("class1");
            if (Condition2) classes.Add("class2");
            return string.Join(",", classes);
        }
    }
    public string Class2
    {
        get { return Condition2 ? 'class2' : ''; }
    }
}
<input data-bind="value: myValue" class="@Model.classes" />

Upvotes: -1

Jared
Jared

Reputation: 2816

I think what you are looking for is something like this:

class1 = @Model.CssClass1;
class2 = @Model.CssClass2;

var viewModel = function(class1, class2) {
    self = this;

    self.classOne= ko.observable(class1);
    self.classOne= ko.observable(class2);

    self.condition_1 = // something
    self.condition_2 = // something
};

ko.applyBindings(new viewModel (class1, class2));

Then just apply the bindings as you showed in your first example:

<tag data-bind="css: { classOne : condition1, classTwo: condition2 }" />

Upvotes: 0

Related Questions