web-dev-qa-db-fra.com

Comment créer de manière concise des attributs HTML facultatifs avec le moteur de vue de rasoir?

Je cherche un moyen d'écrire le code suivant avec moins de lignes de code (peut-être 5). Je suppose que je pourrais faire la même chose que la classe sélectionnée mais cette syntaxe de rasoir n'est pas jolie.

<ul>
@foreach (var mi in Model.MenuItems) {
  <li@(mi.Selected?" class=\"selected\"":null)>
  @if (string.IsNullOrEmpty(mi.Title)) {
    <a href="@mi.Href">@mi.Text</a>
  } else {
    <a href="@mi.Href" title="@mi.Title">@mi.Text</a>
  }
  </li>
}
</ul>
40
JarrettV

Corrigé dans ASP.NET MVC 4

voir http://weblogs.asp.net/jgalloway/archive/2012/02/16/asp-net-4-beta-released.aspx

Rendu d'attribut conditionnel

Si vous avez un attribut qui peut être nul, dans le passé, vous avez dû effectuer une vérification nulle pour éviter d'écrire un attribut vide, comme ceci:

<div @{if (myClass != null) { <text>class="@myClass"</text> } }>Content</div>

Maintenant, Razor est capable de gérer cela automatiquement, vous pouvez donc simplement écrire l'attribut. S'il est nul, l'attribut n'est pas écrit:

<div class="@myClass">Content</div>

Donc, si @myClass est nul, la sortie est juste la suivante:

<div>Content</div>
54
JarrettV

J'ai trouvé une classe HtmlAttribute chaînable et quelques méthodes d'extension Html pour permettre la syntaxe Razor ci-dessous:

<ul> 
    @foreach (var mi in items) { 
    <li @Html.Css("selected", mi.Selected)> 
        <a href="@mi.Href" @Html.Attr("title", mi.Title)>@mi.Text</a> 
    </li> 
    } 
</ul> 

Voici la classe HtmlAttribute:

public class HtmlAttribute : IHtmlString     
{
    private string _InternalValue = String.Empty;
    private string _Seperator;

    public string Name { get; set; }
    public string Value { get; set; }
    public bool Condition { get; set; }

    public HtmlAttribute(string name)
        : this(name, null)
    {
    }

    public HtmlAttribute( string name, string seperator )
    {
        Name = name;
        _Seperator = seperator ?? " ";
    }

    public HtmlAttribute Add(string value)
    {
        return Add(value, true);
    }

    public HtmlAttribute Add(string value, bool condition)
    {
        if (!String.IsNullOrWhiteSpace(value) && condition)
            _InternalValue += value + _Seperator;

        return this;
    }

    public string ToHtmlString()
    {
        if (!String.IsNullOrWhiteSpace(_InternalValue))
            _InternalValue = String.Format("{0}=\"{1}\"", Name, _InternalValue.Substring(0, _InternalValue.Length - _Seperator.Length));
        return _InternalValue;
    }
}

Information supplémentaire: le "séparateur" est utilisé pour enchaîner plusieurs valeurs pour un attribut. Cela peut être utile pour plusieurs noms de classe css (utilisez un espace) ou peut-être utiliser String.Empty pour créer une valeur dépendant de plusieurs conditions (en utilisant la méthode .Add ())

Et voici les méthodes d'assistance de l'extension Html:

public static class Extensions
{
    public static HtmlAttribute Css(this HtmlHelper html, string value)
    {
        return Css(html, value, true);
    }

    public static HtmlAttribute Css(this HtmlHelper html, string value, bool condition)
    {
        return Css(html, null, value, condition);
    }

    public static HtmlAttribute Css(this HtmlHelper html, string seperator, string value, bool condition)
    {
        return new HtmlAttribute("class", seperator).Add(value, condition);
    }

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string value)
    {
        return Attr(html, name, value, true);
    }

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string value, bool condition)
    {
        return Attr(html, name, null, value, condition);
    }

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string seperator, string value, bool condition)
    {
        return new HtmlAttribute(name, seperator).Add(value, condition);
    }
}

Faites-moi savoir s'ils sont utiles.

Merci,

Lee

41
Lee Gunn
<ul>
@foreach (var mi in Model.MenuItems) {
    <li@(mi.Selected?" class=\"selected\"":null)>
        <a href="@mi.Href" @{if(!string.IsNullOrEmpty(mi.Title)) { <text>title="@mi.Title"</text>} }>@mi.Text</a>
    </li>
}
</ul>

Je ne l'ai pas testé mais il analyse correctement.

10
Buildstarted

Ce serait un bon candidat pour un assistant HTML personnalisé:

public static class HtmlExtensions
{
    public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, MenuItem mi)
    {
        var li = new TagBuilder("li");
        if (mi.Selected)
        {
            li.AddCssClass("selected");
        }
        var a = new TagBuilder("a");
        a.MergeAttribute("href", mi.Href);
        if (!string.IsNullOrEmpty(mi.Title))
        {
            a.MergeAttribute("title", mi.Title);
        }
        a.SetInnerText(mi.Text);
        return MvcHtmlString.Create(li.ToString());
    }
}

et selon vous:

<ul>
@foreach (var mi in Model.MenuItems) {
    @Html.MenuItem(mi)
}
</ul>

ou en utilisant des modèles d'affichage, vous n'avez même pas besoin d'écrire une boucle:

<ul>
    @Html.DisplayFor(x => x.MenuItems)
</ul>
7
Darin Dimitrov
<ul>
@foreach (var mi in Model.MenuItems) {
  <li@(Html.Raw((mi.Selected ? " class=\"selected\"" : null))>
    <a href="@mi.Href">@mi.Text</a>
  </li>
}
</ul>
4
Konstantin Tarkus

L'attribut class ne serait pas rendu par Razor si la valeur est null

<a href="#nolink" class="@(categoryId == null ? "submenu-active": null)">All</a>
3
Darius Kucinskas

Pour le cas de plusieurs classes, j'utilise cette méthode d'extension simple:

public static MvcHtmlString If(this string text, bool condition) {
    return new MvcHtmlString(condition ? text : string.Empty);
}

Et dans la vue:

<div class="menuitem @("active".If(Model.Active))">
1
Robert Massa