0

I am iterating round a model's comments (a collection of Comment objects), and need to style them based on whether the property Private is true or false.

I tried to add a class based on a property like this:

<div class="contact-card comment_p_@(comment.Private)">

But the generated html keeps giving me

<div class="contact-card comment_p_class">

Even though I have directly below this element

<p>@comment.Private</p>

which outputs <p>True</p> or <p>False</p> as appropriate.

Here is the full loop:

@foreach (var comment in comments)
{
    <div class="contact-card comment_p_@comment.Private">
        <strong>@comment.UserName</strong>
        <p>@comment.Private</p>
        <strong class="pull-right">@comment.DateTime</strong>
        <p style="white-space: pre-wrap;">@comment.Content</p>
    </div>
}

And output of one iteration:

<div class="contact-card comment_p_class">
    <strong>skotze</strong>
    <p>True</p>
    <strong class="pull-right">29/11/2017 03:18:12</strong>
    <p style="white-space: pre-wrap;">asda123</p>
</div>

I also tried

<div class="contact-card comment_p_@comment.Private">
<div class="@comment.Private">
<div class="comment-@comment.Private">

But I always get the same results...when I try to set the class using the property, the output html changes it to just class, even though I am able to print the true value when its just in a <p>.

What is going on here?

Bassie
  • 9,529
  • 8
  • 68
  • 159

2 Answers2

2

To explain the behavior, there are 2 types of 'conditional attributes' in razor-2.

For attributes that expect a string value, for example class="someValue", then when you use

@{
    string classname = "myclass";
    string noclass = null;
}
<div class="@classname">xx</div>
<div class="@noclass">xx</div>

Then the output will be

<div class="myclass">xx</div>
<div>xx</div>

When the value of the property is null, it omits the attribute, otherwise it generates the attribute with the value of the property.

The other type is used for boolean attributes, such as generating a checked="checked" attribute.

When you use

@{
    bool checked = true;
    bool notchecked = false;
}
<input type="checkbox" checked="@checked" />
<input type="checkbox" checked="@notchecked" />

Then the output will be

<input type="checkbox" checked="@checked" />
<input type="checkbox" />

When the value of the property is true, it adds the attribute with the same value as the name of the attribute - i.e. checked="checked" and when the value is false it omits the attribute.

In your case, the property is a bool with a value of true so the razor engine generates the value as the same name as the attribute - i.e. "class" and appends it to the existing value and the result is

<div class="contact-card comment_p_class">

Had the value of the property been false it would have generated just

<div class="contact-card comment_p_">

As noted in your self answer, it is necessary to use

<div class="contact-card @(comment.Private ? "comment-priv" : "comment-pub" )">

or similar conditional code to generate the class attribute.

  • Thanks Stephen, yes I did notice that a False value generated `comment_p_` so that makes a lot of sense – Bassie Nov 29 '17 at 05:10
0

I managed to get around this by copying this answer:

<div class="contact-card @(@comment.Private ? "comment-priv" : "comment-pub" )">

But accoring to this answer, my original attempt should work.

If anyone can explain why it behaves like that I will accept their answer.

Bassie
  • 9,529
  • 8
  • 68
  • 159
  • I think your misunderstanding how Razor-2 conditional attributes work (the 2nd link you gave as not related to your situation) –  Nov 29 '17 at 04:44