Alan2
Alan2

Reputation: 24562

How can I make an unordered list appear within a foreach loop in MVC3 Razor?

I have the following code:

@foreach (Content topic in Model.Topics)
{
    if (topic.RowKey.Substring(2, 2) == "00")
    {
        <h3>@topic.RowKey.Substring(0, 2).TrimStart('0') - @Html.Raw(topic.Title)</h3>
    }
    else
    {
        <p>@String.Format("{0}.{1}",topic.RowKey.Substring(0, 2).TrimStart('0'),topic.RowKey.Substring(2, 2).TrimStart('0').PadLeft(1, '0')) - @Html.Raw(topic.Title)</p>
    }
}

My input data (value of topic.RowKey) looks like this:

0100 <- This is topic 1
0101 <- This is topic 1.1
0102 <- This is topic 1.2
0103 <- This is topic 1.3
0200 <- This is topic 2
0201 <- This is topic 2.1
etc....

This works but what I would really like to do is to have an h3 heading every time the first two digits of the RowKey change and then between then and then next h3 heading I would like to have an unordered list instead of just <p>xxx</p>. I have tried lots of different combinations of things but nothing works. Is this even possible to do with Razor? Where I had huge problems was how can I get the <ul> and </ul>s to appear correctly? I know I can put a <ul> after the <h3> but how can I place the </ul>?

Upvotes: 2

Views: 11452

Answers (4)

Michael Grassman
Michael Grassman

Reputation: 1935

    @{bool isFirst = true;}
    @foreach (Content topic in Model.Topics)
    {
        if (topic.RowKey.Substring(2, 2) == "00")
        {
            if(!isFirst) {
               <text></ul></text>
               isFirst = false
            }
            <h3>@topic.RowKey.Substring(0, 2).TrimStart('0') - @Html.Raw(topic.Title)</h3>
        }
        else
        {   
            <li>
            <p>@String.Format("{0}.{1}",topic.RowKey.Substring(0, 2).TrimStart('0'),topic.RowKey.Substring(2, 2).TrimStart('0').PadLeft(1, '0')) - @Html.Raw(topic.Title)</p></li>
        }
    }

    </ul>

Upvotes: 0

YavgenyP
YavgenyP

Reputation: 2123

Its not about razor, this is something you can solve with any rendering enginge, web or windows forms or anything else.

@model List<Topic>
@{
int currentKey = 0;
bool withinUL = false;
foreach (Topic topic in Model) 
{ 
    if (topic.RowKey != currentKey)   
    {
        currentKey = topic.RowKey;
        if (withinUL)
        {
            withinUL = false;
            @:</ul>
        }


        @:<h3>@topic.RowKey - @Html.Raw(topic.Title)</h3>     

    }   
    else   
    {       
        if (!withinUL)
        {
            withinUL = true;
            @:<ul></ul>
        }
          @:<li>@topic.RowKey - @Html.Raw(topic.Title)</li>  
    }
}
} 

Upvotes: 0

Zach dev
Zach dev

Reputation: 1620

It would be more easy create a model parent-child, populated before send it to the view

the model

public class topic {

        //everything else
        public List<topic> subtopic{ get; set; }

    }

the view

@foreach (Content topic in Model.Topics)
{
    <h3>@topic.RowKey.Substring(0, 2).TrimStart('0') - @Html.Raw(topic.Title)</h3>
    if (topic.subtopic.count > 0)
    {
        <ul>
            @foreach (Content subtopic in topic.subtopic)
            { 
                <li>@String.Format("{0}.{1}", topic.RowKey.Substring(0, 2).TrimStart('0'), topic.RowKey.Substring(2, 2).TrimStart('0').PadLeft(1, '0')) - @Html.Raw(topic.Title)</li>
            }
        </ul>
    }
}

Upvotes: 0

Rapha&#235;l Althaus
Rapha&#235;l Althaus

Reputation: 60493

not checked in razor, there may be an @ missing here or there, but...

@var groupedTopics = Model.Topics.GroupBy(t => t.RowKey.Substring(0, 2));

@foreach (var group in groupedTopics) {
  var firstTopic = group.First();
  <h3>@firstTopic.RowKey.Substring(0, 2).TrimStart('0') - @Html.row(firstTopic.Title)</h3>
  <ul>
  @foreach (var topic in group.Skip(1)) {
      <li>@String.Format("{0}.{1}",topic.RowKey.Substring(0, 2).TrimStart('0'),topic.RowKey.Substring(2, 2).TrimStart('0').PadLeft(1, '0')) - @Html.Raw(topic.Title)</li>
  }
  </ul>

}

Upvotes: 8

Related Questions