Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested binding using @bind-xxx syntax does not work #11679

Closed
conficient opened this issue Jun 28, 2019 · 9 comments
Closed

Nested binding using @bind-xxx syntax does not work #11679

conficient opened this issue Jun 28, 2019 · 9 comments
Labels
area-blazor Includes: Blazor, Razor Components question

Comments

@conficient
Copy link
Contributor

Describe the bug

Binding values using @bind-XXX binding syntax does not work if nested.

Demo

BlazorBug04

To Reproduce

Steps to reproduce the behavior:

  1. Create a Blazor client-side application using Preview6
  2. Create a new custom control that also uses @bind-Value syntax in the Shared folder
  3. Create an EditForm in the Index.razor page and a model to bind to
  4. Create an InputText component, bind using @bind-Value to one model property
  5. Create a custom control instance using @bind-Value

Expected behavior

Expected the binding to work with nested controls, so both properties of the model are updated when the input control is changed.

Actual behavior

A direct binding with InputText works but the custom control binding does not bind to the model. It binds when initially created but updates to the control do not get passed back the to page model.

Sample code

Example repo created at https://github.com/conficient/BlazorBug04

MyControl.razor

<div class="form-control">
    <label>@Label</label>
    <InputText @bind-Value="@Value" />
</div>

@code {
    // binding parameters

    [Parameter] public string Value { get; private set; }

    [Parameter] public EventCallback<string> ValueChanged { get; private set; }

    [Parameter] public string Label { get; private set; }
}

Index.razor

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<EditForm Model="@model">
    A: <InputText @bind-Value="@model.A" /><br />
    <MyControl @bind-Value="@model.B" Label="B" />
</EditForm>

<b>Binding check:</b>
<p>A = @model.A</p>
<p>B = @model.B</p>
@code
{
/// <summary>
/// Data class
/// </summary>
public class Model
{
    public string A { get; set; }
    public string B { get; set; }
}

private Model model = new Model()
{
    A = "initial A",
    B = "intial B"
};
}

Additional context

Previously reported on Blazor repo: #1490
Also reported in aspnetcore repo: #5504
Related: #6351 was supposed to fix?

Include the output of dotnet --info

.NET Core SDK (reflecting any global.json):
 Version:   3.0.100-preview6-012264
 Commit:    be3f0c1a03

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17763
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.0.100-preview6-012264\

Host (useful for support):
  Version: 3.0.0-preview6-27804-01
  Commit:  fdf81c6faf

.NET Core SDKs installed:
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.401 [C:\Program Files\dotnet\sdk]
  2.1.505 [C:\Program Files\dotnet\sdk]
  2.1.604 [C:\Program Files\dotnet\sdk]
  2.1.700-preview-009618 [C:\Program Files\dotnet\sdk]
  2.1.700 [C:\Program Files\dotnet\sdk]
  2.1.800-preview-009677 [C:\Program Files\dotnet\sdk]
  2.1.800-preview-009696 [C:\Program Files\dotnet\sdk]
  2.2.103 [C:\Program Files\dotnet\sdk]
  3.0.100-preview6-012264 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview6.19307.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview6-27804-01 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0-preview6-27804-01 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download
@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Jun 28, 2019
@mkArtakMSFT
Copy link
Member

Thanks for contacting us, @conficient .
You can write it this way, and the changes would propagate.

<InputText Value="@Value" ValueChanged="@ValueChanged" />

Alternatively, you can simply subclass from the InputText component.

@conficient
Copy link
Contributor Author

I tried the approach you suggested but this results in a WASM error:

WASM: System.InvalidOperationException: Microsoft.AspNetCore.Components.Forms.InputText requires a value for the 'ValueExpression' parameter. Normally this is provided automatically when using 'bind-Value'

I think this is because the ValueChanged event handler isn't set?
I resolved my issue anyway once I realised (thanks to @joshlang ) that I needed to invoke the ValueChanged from the Value property setter.

I will push the updated version on this code to my repo. This issue can remain closed though.

@rynowak
Copy link
Member

rynowak commented Jul 1, 2019

If your goal is to wrap up an InputText in some bootstrap styling, I would suggest subclassing. The form types are designed for this use case.

If you're really determined to compose, then accept an Expression<Func<string>> ValueExpression as a parameter as well and pass that through also.

@conficient
Copy link
Contributor Author

Thanks @rynowak - yes I wanted to get rid of boilerplate <div class="form-group"><label>.... around each input control so my forms are simpler. I'll try what you suggest.

@3x0dv5
Copy link

3x0dv5 commented Jul 5, 2019

I started to see the following error after upgrading from preview5 to preview6

WASM: System.InvalidOperationException: Microsoft.AspNetCore.Components.Forms.InputText requires a value for the 'ValueExpression' parameter. Normally this is provided automatically when using 'bind-Value'

this is my custom component
the razor file

@inherits CcInputTextComponent
@using Microsoft.AspNetCore.Components
<input type="@Type" 
       class="@CssClass"
       id="@Id"
       value="@BindMethods.GetValue(CurrentValue)" 
       onchange="@BindMethods.SetValueHandler(__value => CurrentValue = __value, CurrentValue)"
       placeholder="@PlaceHolder"
/>

the "code behind" - I prefer not to use the @ code{} I like the idea of having the csharp completely separated from the razor

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.RenderTree;

namespace BzTest.Shared.CcInputText
{
    public class CcInputTextComponent: InputText
    {
        [Parameter] public string Type { get; set; } = "text";
        
        [Parameter] public string PlaceHolder { get; set; }
         
    }
}

the use of the component

<CcInputText id="Password" Type="password" bind-Value="@loginRequest.Password" Class="form-control input_pass" PlaceHolder="Password"></CcInputText>

@joshlang
Copy link

joshlang commented Jul 5, 2019

use @bind-Value instead of bind-Value. See the preview6 upgrade notes for more details

@3x0dv5
Copy link

3x0dv5 commented Jul 6, 2019

Yep, that seems to work. I get a red squiggle but might be Resharper's fault.

image

I don't know looks weird, not the squiggle, the syntax. The @ before the attribute name, I don't know it's different from the rest of the Razor syntax, maybe just have to get used to.

@ghost
Copy link

ghost commented Aug 25, 2019

For those that end up here like me, it appears as though "@bind-Value" became case sensitive at some point.

@joshlang
Copy link

Yes it did. Which now allows us to create components like which don't interfere with the html tag (YAY!)

@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components question
Projects
None yet
Development

No branches or pull requests

5 participants