Как передать данные из дочернего компонента в его родительский в C# Blazor с помощью элемента ввода?

Я столкнулся с проблемой при попытке использовать повторно используемый компонент ввода для создания нового профиля пользователя. Когда я пытаюсь создать нового пользователя, все данные, введенные в повторно используемый компонент, кажутся пустыми. Я подозреваю, что это связано с проблемой передачи данных от дочернего компонента к родительскому. Интересно, что когда я использую стандартный тег, все работает нормально. Будем очень признательны за любые идеи или предложения о том, как решить эту проблему. Заранее спасибо! Главная страница AddProfile.razor

<form> 
       <div class = "col-md-6">
                <Label LabelClass = "small mb-1"  LabelText = "@Loc[nameof(ResourcesEnum.GeneralFirstName)]"/>
                <Input InputPlaceholder = "@Loc[nameof(ResourcesEnum.GeneralEnterFirstName)]" BindValue = "@_contact.FirstName" InputClass = "form-control" />
            </div>

        ...

    <div class = "btn-wrapper">
        <Button BtnClass = "btn btn-primary" IconClass = "bi bi-plus-lg" OnClick = "Submit" />
        <Button BtnClass = "btn btn-danger" IconClass = "bi bi-x-circle" OnClick = "() => CancelModalWindow()" DataToggle = "modal" DataTarget = "#exampleModal"/>
    </div>
    </form>

@code {

    private ContactDTO _contact = new ContactDTO();
    private List<PartnerDTO>? _partners = new List<PartnerDTO>();
    private bool _switchAddPartner = false;
    private ModalBootstrap? _modalComponent;
    private string? _returnUrl;
    private string _submitText = "Save contact";
    private string _exam;
    
    protected override async Task OnInitializedAsync()
    {
        _partners = (await PartnerService.GetAllPartners())?.ToList();
        var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
        if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("returnUrl", out var url))
        {
            _returnUrl = url!;
            _submitText = "Save and return";
        }
    }
    
    void HandleInputValueChanged(string value)
    {
        // Update the input value in the parent component
        _contact.FirstName = value;
    }
    
    private void HandleInputData(string inputValue)
    {
        _contact.FirstName = inputValue;
        Console.WriteLine($"it is value input: {_contact.FirstName}!!!!!");
    }
    
    private void NavigateUrlContactsPage()
    {
        NavigationManager.NavigateTo("/contacts");
    }
    
    private void Cancel()
    {
        if (!string.IsNullOrEmpty(_returnUrl))
        {
            NavigationManager.NavigateTo(_returnUrl);
        }
        else
        {
            NavigateUrlContactsPage();
        }
    }
    
    private async Task Submit()
    {
        Console.WriteLine($"Before Submit: {_contact.FirstName}");
        try
        {
            var createdContact = await ContactService.CreateContactAsync(_contact);
            
            if (!string.IsNullOrEmpty(_returnUrl))
            {
                Console.WriteLine(createdContact.FirstName);
                var returnUrlWithNewContact = $"{_returnUrl}?newContactId = {createdContact.Id}";
                NavigationManager.NavigateTo(returnUrlWithNewContact);
            }
            else
            {
                Console.WriteLine($"Error{_contact.FirstName}");
                NavigateUrlContactsPage();
            }
            Snackbar.Add($"\u2795 {_contact.FullName}", Severity.Success);
        }
        catch (Exception ex)
        {
            Snackbar.Add($"{@Loc[nameof(ResourcesEnum.GeneralError)]}: {ex.Message}", Severity.Error);
        }
    }
    
    private void CancelModalWindow()
    {
        _modalComponent.ShowModal($"{@Loc[nameof(ResourcesEnum.GeneralConfirmExit)]}", $"{@Loc[nameof(ResourcesEnum.GeneralConfirmExitQuestion)]}",()=>Cancel() );
    }

}

Input.razor (многоразовый компонент)

<input class = "@InputClass" type = "@InputType" placeholder = "@InputPlaceholder" @bind = "@BindValue"/>

@code {
    [Parameter] public string InputType { get; set; }
    [Parameter] public string InputClass { get; set; }
    [Parameter] public string InputPlaceholder { get; set; }
    [Parameter] public string BindValue { get; set; }
}

Найдите в blazor пользовательские входные данные любое количество ресурсов, которые покажут вам, как правильно выполнять привязку. Вы также можете просмотреть стандартный код InputText, чтобы узнать, как это делается — github.com/dotnet/aspnetcore/blob/main/src/Components/Web/sr‌​c/…

MrC aka Shaun Curtis 27.04.2024 13:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я воссоздал ваш компонент и надеюсь, что все работает нормально. Ниже мой CInput. Я только изменил привязки, чтобы они работали правильно. В blazor @bind-SomeValue упрощен синтаксис для обработки двух отдельных параметров. Одно — это значение для передачи, а другое — значение, которое нужно получить с помощью EventCallback. Чтобы это работало, оба параметра должны иметь одинаковое имя, но в EventCallback необходимо добавить слово «Изменено» в конце. Когда я использую его, строка передается в обе стороны. Если это не ваша проблема, оставьте отзыв.

<input class = "@ParamInputClass" type = "@ParamInputType" placeholder = "@ParamInputPlaceholder" value = "@ParamBindValue" @onchange = "OnValueChanged" />

@code {
    [Parameter] public string ParamInputType  { get; set; } = "text";
    [Parameter] public string ParamInputClass { get; set; } = string.Empty;
    [Parameter] public string ParamInputPlaceholder { get; set; } = string.Empty;

    [Parameter] public string ParamBindValue { get; set; } = string.Empty;
    [Parameter] public EventCallback<string> ParamBindValueChanged { get; set; }

    protected async Task OnValueChanged(ChangeEventArgs? val)
    {
        if (val is null || val.Value is null) { return; }
        string ConvertedToString = ((string) val.Value) ?? string.Empty ;
        // Add whatever logic here or even some validation if not using fluent validation on form
        await ParamBindValueChanged.InvokeAsync(ConvertedToString);
    }
}

А вот компонент, который его использует.

<CInput ParamInputType = "text" ParamInputPlaceholder = "Some Text" ParamInputClass = "fs-3"   @bind-ParamBindValue = "@Text" />

<div>
    @Text
</div>

@code {
    string Text = "Start value";
}

это мне очень помогло и сработало для меня. Можете ли вы объяснить, что происходит в функции OnValueChanged?

Mr How 27.04.2024 23:01

onchange — это EventCallback<ChangeEventArgs>, поэтому мне нужно либо иметь тот тип объекта, который привязывается к нему, либо метод с правильной сигнатурой. К сожалению, возвращаемое значение является объектом, поэтому мне нужно выполнить преобразование. Первые строки — это просто проверки для устранения предупреждений. Однако, поскольку вы выбираете тип ввода по значению параметра, это может быть int, datetime или любой другой формат. Поэтому вам необходимо внести изменения в метод OnValueChanged, чтобы проверить, какое значение типа. Я не знаю, чего вы хотите добиться, но, возможно, лучше использовать дженерики в компоненте бритвы.

Artur Chrzanowski 28.04.2024 16:19

Другие вопросы по теме