How to bind object to property on click using CoC DotVVM

138 Views Asked by At

I created my own Code only Component for Accordion. It looks like on picture below.

enter image description here

Lines with blue arrows are article sections and those with red line are articles. What I want to archieve is on page load I will get only root article sections, nothing else. When I will click on "TEST" I will send get request with ID to load more items.

My problem is I cannot get object on which I clicked into my property in ViewModel. I created SelectedValueProperty for this purpose and register it in static constructor. After that I override GetControlBinding method and added property into group. However when I click on item in my view, nothing is assigned to my SelectedValueProperty.

Here is my code of CoC

public class Accordion : HierarchyItemsControlBase
{
    public static readonly DotvvmProperty SelectedValuesProperty;
    public static readonly DotvvmProperty ChangedProperty;
    protected override HtmlContents CreateItemContents(DataItemContainer dataItem)
    {
        var contents = base.HtmlFactory.CreateContents();
        return contents;
    }

    public Accordion() : base("div")
    {

    }

    static Accordion()
    {
        SelectedValuesProperty = DotvvmProperty.Register<IEnumerable, Accordion>(c => c.SelectedValues, null, false);
        ChangedProperty = DotvvmProperty.Register<Command, Accordion>(c => c.Changed, null);
    }

    #region Properties

    public List<ArticleSectionListDTO> DataSource
    {
        get => (List<ArticleSectionListDTO>)GetValue(DataSourceProperty);
        set => SetValue(DataSourceProperty, value);
    }

    public IEnumerable SelectedValues
    {
        get => GetValue(SelectedValuesProperty, true) as IEnumerable;
        set => SetValue(SelectedValuesProperty, value);
    }

    public Command Changed
    {
        get => GetValue(ChangedProperty) as Command;
        set => SetValue(ChangedProperty, value);
    }

    public Command Click { get; set; }
    #endregion


    protected override ControlBindingGroup GetControlBinding()
    {
        var controlBinding = base.GetControlBinding();
        controlBinding.Add(this, SelectedValuesProperty);
        return controlBinding;
    }


    protected override void AddAttributesToRender(IHtmlWriter writer, IDotvvmRequestContext context)
    {
        writer.AddControlKnockoutDataBind<Accordion>(GetControlBinding());

        Attributes.Add("class", "accordion");
        base.AddAttributesToRender(writer, context);

        var clickBinding = GetCommandBinding(ChangedProperty);
        if (clickBinding != null)
        {
            writer.AddAttribute("onclick", KnockoutHelper.GenerateClientPostBackScript(nameof(Click), clickBinding, this), true, ";");
        }
    }

    public void DataBind(IDotvvmRequestContext context)
    {
        //some code here
    }

    public void DataBindItem(DotvvmControl parent, ArticleSectionListDTO item, IDotvvmRequestContext context)
    {
         //some code here
    }

    protected override void RenderContents(IHtmlWriter writer, IDotvvmRequestContext context)
    {
        DataBind(context);
        base.RenderContents(writer, context);
    }
}

Here is my ViewModel where AccordionList serves as datasource and AccordionSelected has to serve as a storage of object on which I clicked.

public List<ArticleSectionListDTO> AccordionList { get; set; } = new List<ArticleSectionListDTO>();
public List<ArticleSectionListDTO> AccordionSelected { get; set; } = new List<ArticleSectionListDTO>();

How I use it in view

<coc:Accordion DataSource="{value: AccordionList}" 
       ItemChildrenBinding="{{value: HasCategories}}" 
       SelectedValues="{{value: AccordionSelected}}">
</coc:Accordion>     
0

There are 0 best solutions below