Можно ли инициализировать все Taghelpers перед обработкой?

У меня есть один TagHelper, который создает контекст в своем Init методе:

public class TabContext
{
    public bool HasExplicitActiveItem { get; set; }
    public bool HasActiveItem { get; set; }
}

В дочерних Taghelper я пытаюсь установить HasExplicitActiveItem, если этот taghelper имеет атрибут Html (bool IsActive), установленный на true:

public override void Init(TagHelperContext context)
{
    //...
    if (IsActive)
    {
        _tabContext.HasExplicitActiveItem = true;
    }
}

Теперь, когда taghelpers инициализирован, а HasExplicitActiveItem неверно, я хочу установить состояние IsActive из первого дочернего taghelper:

public override void Process(TagHelperContext context, TagHelperOutput output)
{
    //...
    if (_tabContext.HasActiveItem)
    {
        IsActive = false;
    }
    else if (!_tabContext.HasExplicitActiveItem)
    {
        IsActive = true;
    }
    if (IsActive)
    {
        _tabContext.HasActiveItem = true;
    }
    //...
}

Однако это не работает, потому что каждый помощник дочернего тега инициализируется и обрабатывается до инициализации следующего помощника дочернего тега.

Для их вызова я использую await output.GetChildContentAsync() из родительского тега-помощника.

Так можно ли сначала инициализировать всех (прямых) дочерних элементов, а затем обработать их? Если нет, есть ли способ предварительно сканировать свойства детей?


Сомневаюсь, у меня проблема XY, желаемая разметка такая:

<tab>
    <tab-pane />
    <tab-pane />
    <tab-pane is-active="true" />
    <tab-pane />
</tab>

Если is-active не установлен, я хочу установить is-active на первом tab-pane.


person Christian Gollhardt    schedule 07.03.2018    source источник


Ответы (1)


Решил проблему, ничего не выводя от детей.

Я сопоставил все дочерние данные с контекстом элемента:

public class TabPaneContext
{
    public IHtmlContent Content { get; set; }
    public string Id { get; set; }
    public bool IsActive { get; set; }
    public string Title { get; set; }
}

Основной контекст получает только список контекста элемента:

public class TabContext
{
    public IList<TabPaneContext> Items { get; set; }
}

Дочерние элементы Taghelper сохраняют актуальное содержимое в контексте элемента:

public class TabPaneTagHelper : TagHelper
{
    private TabContext _tabContext;
    private TabPaneContext _tabPaneContext = new TabPaneContext();

    public string Id
    {
        get => _tabPaneContext.Id;
        set => _tabPaneContext.Id = value;
    }
    public bool IsActive
    {
        get => _tabPaneContext.IsActive;
        set => _tabPaneContext.IsActive = value;
    }
    public string Title
    {
        get => _tabPaneContext.Title;
        set => _tabPaneContext.Title = value;
    }

    public override void Init(TagHelperContext context)
    {
        _tabContext = context.Items[typeof(TabContext)];
        _tabContext.Items.Add(_tabPaneContext);
    }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        _tabPaneContext.Content = await output.GetChildContentAsync();
        output.SuppressOutput();
    }

Фактическая генерация вывода выполняется основной функцией taghelper путем итерации по элементам.

Не уверен, насколько это эффективно, но работает. По-прежнему кажется немного грязным.

person Christian Gollhardt    schedule 07.03.2018