@ref attribute

At what point is the property bound to @ref initialized in the life cycle and when is it safe to use?
My experiments with the code below seem to indicate that it is not populated until the control is actually used on the page.
This
<h3>@(MultiSelect==null)</h3>
Only prints true after Items are selected (even when like below I am pre selecting some items)

It just seems strange that i can do this
 MultiVal  = new string[2];
   MultiVal[0= "AU";
   MultiVal[1= "DE";
in OnInitialized() But trying to access the MultiSelect to use AddItem() gets a null reference exception.


@page "/counter"
@using Syncfusion.EJ2.Blazor.DropDowns
@using Syncfusion.EJ2.Blazor.Buttons





<div class="control-section col-lg-12 checkbox">
    <div class="col-lg-9">
        <div class='content multiselect-checkbox'>
            <EjsMultiSelect   TValue="string[]" Placeholder="Select countries" 
               Value="@MultiVal"
                @ref="@MultiSelect"
                
                Mode="@VisualMode.CheckBox" DataSource="@Country" ShowSelectAll="@ShowSelectAllCheckBox" EnableSelectionOrder="@EnableSelectionOrders" ShowDropDownIcon="@EnableDropDownIcon" FilterBarPlaceholder="Search countries" PopupHeight="350px">
                <MultiSelectFieldSettings Text="Name" Value="Code"></MultiSelectFieldSettings>
                <MultiSelectEvents TValue="string[]" ValueChange="onChange"></MultiSelectEvents>
                
            </EjsMultiSelect>
        </div>
    </div>
    <div class="col-lg-3">
        <div class='content property-section'>
            <table>
                <tr>
                    <td>
                        <EjsCheckBox Label="ShowSelectAll" @bind-Checked="@checkSelectAll" ValueChange="@OnSelectAllChange"></EjsCheckBox>
                    </td>
                </tr>
                <tr>
                    <td>
                        <EjsCheckBox Label="DropDown Button" @bind-Checked="@dropdownButton" ValueChange="@OnDropDownButtonChange"></EjsCheckBox>
                    </td>
                </tr>
                <tr>
                    <td>
                        <EjsCheckBox Label="Selection reorder" @bind-Checked="@selectionReorder" ValueChange="@OnSeletionReorder"></EjsCheckBox>
                    </td>
                </tr>
            </table>
        </div>
    </div>
    <h4>@(string.Join(","@MultiVal))</h4>
    <h3>@(MultiSelect==null)</h3>
</div>

@code{

EjsMultiSelect<string[]> MultiSelect; 

    public string[] MultiVal { getset; } = new string[] { };
    public bool ShowSelectAllCheckBox { getset; } = true;
    public bool EnableSelectionOrders { getset; } = true;
    public bool EnableDropDownIcon { getset; } = true;
    private bool checkSelectAll { getset; } = true;
    private bool dropdownButton { getset; } = true;
    private bool selectionReorder { getset; } = true;
    public void OnSelectAllChange(Syncfusion.EJ2.Blazor.Buttons.ChangeEventArgs args)
    {
        this.ShowSelectAllCheckBox = args.Checked;
    }
    public void OnDropDownButtonChange(Syncfusion.EJ2.Blazor.Buttons.ChangeEventArgs args)
    {
        this.EnableDropDownIcon = args.Checked;
    }
    public void OnSeletionReorder(Syncfusion.EJ2.Blazor.Buttons.ChangeEventArgs args)
    {
        this.EnableSelectionOrders = args.Checked;
    }
private void onChange(MultiSelectChangeEventArgs<string[]> args)
{
    MultiVal = args.Value;
    
    StateHasChanged();

}

protected override void OnInitialized()
MultiVal  = new string[2];
   MultiVal[0= "AU";
   MultiVal[1= "DE";
   
}
protected override void OnAfterRender(bool firstRender)
{
   
      
    
}
 

    public class Countries
    {
        public string Name { getset; }
        public string Code { getset; }
    }
    List<Countries> Country = new List<Countries>
{
        new Countries() { Name = "Australia"Code = "AU" },
        new Countries() { Name = "Bermuda"Code = "BM" },
        new Countries() { Name = "Canada"Code = "CA" },
        new Countries() { Name = "Cameroon"Code = "CM" },
        new Countries() { Name = "Denmark"Code = "DK" },
        new Countries() { Name = "France"Code = "FR" },
        new Countries() { Name = "Finland"Code = "FI" },
        new Countries() { Name = "Germany"Code = "DE" },
        new Countries() { Name = "Greenland"Code = "GL" },
        new Countries() { Name = "Hong Kong"Code = "HK" },
        new Countries() { Name = "India"Code = "IN" },
        new Countries() { Name = "Italy"Code = "IT" },
        new Countries() { Name = "Japan"Code = "JP" },
        new Countries() { Name = "Mexico"Code = "MX" },
        new Countries() { Name = "Norway"Code = "NO" },
        new Countries() { Name = "Poland"Code = "PL" },
        new Countries() { Name = "Switzerland"Code = "CH" },
        new Countries() { Name = "United Kingdom"Code = "GB" },
        new Countries() { Name = "United States"Code = "US" },
    };
    public string RemoteQuery = "new ej.data.Query().select(['FirstName']).take(10).requiresCount()";
}
<style>
    .property-section .e-checkbox-wrapper {
        margin: 10px;
    }
    .control-section.checkbox {
        margin-top: 20px;
    }
    .multiselect-checkbox {
        width: 70%;
        margin-left: 70px;
    }
</style>


1 Reply

SP Sureshkumar P Syncfusion Team March 17, 2020 10:40 AM UTC

Hi Richard, 
 
Greetings from Syncfusion support. 
 
 
Query 1: At what point is the property bound to @ref initialized in the life cycle and when is it safe to use?  
 
Answer:  
            We can get the @ref in the OnAfterRender life cycle.  
 
Query 2: Only prints true after Items are selected (even when like below I am pre selecting some items) 
It just seems strange that i can do this  
 
Answer:  
            We can preselect the value by changing the below code instead of yours. 
 
protected override void OnInitialized() 
    { 
        MultiVal  = new string[] { "AU", "DE" }; 
 
    } 
 
Query 3: in OnInitialized()  But trying to access the MultiSelect  to use AddItem() gets a null reference exception.  
 
Answer:  
            We can add the items by our DataBound event. But in your scenario (preselect value). We can add the item by OnAfterRender life cycle 
 
Kindly refer the below code example. 
 
<EjsMultiSelect   TValue="string[]" Placeholder="Select countries"  
               Value="@MultiVal" 
                @ref="@MultiSelect" 
                 
                Mode="@VisualMode.CheckBox" DataSource="@Country" ShowSelectAll="@ShowSelectAllCheckBox" EnableSelectionOrder="@EnableSelectionOrders" ShowDropDownIcon="@EnableDropDownIcon" FilterBarPlaceholder="Search countries" PopupHeight="350px"> 
                <MultiSelectFieldSettings Text="Name" Value="Code"></MultiSelectFieldSettings> 
                <MultiSelectEvents TValue="string[]" DataBound="@DataBounded" ValueChange="onChange"></MultiSelectEvents> 
                 
            </EjsMultiSelect> 
 
@code{ 
protected void DataBounded() 
    { 
         
        this.MultiSelect.AddItem(new List<Countries>() { new Countries() { Name = "Australia2", Code = "AU2" } }, 6  ); 
 
 
    } 
} 
 
Regards, 
Sureshkumar P 


Loader.
Up arrow icon