功能已执行,我不知道为什么
Function is executed and i dont know why
我是 blazor 的新手,有一个我不明白的问题。
我写了一个简单的测试应用程序,我可以在其中创建联系人、文章和发票。这行得通。在发票中,我可以通过打开模式和 select 一些文章来创建发票行项目,然后获得新的发票行项目。
现在我有两个 problems/questions:
- 当我删除最后一个发票行项目时它有效,但是当我删除另一个而不是最后一个项目时,函数
SaveInvoice
被执行。
- 如果我将模式代码放在
<Editform>
标签内,函数 SaveInvoice
也会被执行。如果我将模式放在 <Editform>
标签之外,它会按预期工作,但我想将它放在表单内。
为什么没有显式调用就执行了这段代码?我想有某种隐式调用,但我不明白它来自哪里。
你能帮我或给我提示吗?或者您需要更多信息?
发票表单调用代码:
@page "/invoice/edit/{rechnungID:int}"
@inject NavigationManager navMan
@inject IJSRuntime js
@inject IInvoiceRepository invoiceRepository
@inject IArticleRepository articleRepository
<h3>Rechnung bearbeiten</h3>
<FormInvoice ButtonText="Aktualisieren" Artikel="@Artikel" Rechnung="@Rechnung" Positionen="@Positionen" OnValidSubmit="@SaveInvoice" EditMode="true" OnCancel="@Cancel" OnRemoveItem="@RemoveItem" />
@code {
[Parameter] public int rechnungID { get; set; }
Rechnung Rechnung = new Rechnung();
List<Rechnungsposition> Positionen { get; set; } = new List<Rechnungsposition>();
List<Artikel> Artikel { get; set; } = new List<Artikel>();
protected async override Task OnInitializedAsync()
{
Rechnung = await invoiceRepository.GetInvoiceByID(rechnungID);
Positionen = Rechnung.Positionen;
Artikel = await articleRepository.GetArticles();
}
async Task SaveInvoice() // This gets executed and i dont know why
{
await invoiceRepository.UpdateInvoice(Rechnung);
await js.InvokeVoidAsync("alert", $"Erfolgreich aktualisiert!");
navMan.NavigateTo("invoice");
}
void Cancel() => navMan.NavigateTo("invoice");
private void RemoveItem(Rechnungsposition pos)
{
Positionen.Remove(pos);
}
}
发票表格代码:
@inject IModalService Modal
@inject IArticleRepository articleRepository
@inject IInvoiceRepository invoiceRepository
@inject IInvoiceLineItemRepository itemsRepository
<EditForm Model="@Rechnung" OnValidSubmit="@OnValidSubmit">
<DataAnnotationsValidator />
<div class="form-group row">
<label class="col-sm-1 col-form-label" for="inputReNr">Rechnungsnr:</label>
<div class="col-sm-2">
@if (EditMode)
{
<InputText id="inputReNr" class="form-control-plaintext" @bind-Value="@Rechnung.RechnungsNr" readonly />
}
else
{
<InputText id="inputReNr" class="form-control" @bind-Value="@Rechnung.RechnungsNr" />
@*<ValidationMessage For="@(() => Rechnung.RechnungsNr)" />*@
}
</div>
<label class="col-sm-1 col-form-label" for="inputReDatum">Datum:</label>
<div class="col-sm-2">
<InputDate id="inputReDatum" class="form-control" @bind-Value="@Rechnung.RechnungsDatum" />
<ValidationMessage For="@(() => Rechnung.RechnungsDatum)" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-1 col-form-label" for="inputAdresse">Adresse:</label>
<div class="col-sm-5">
<InputTextArea id="inputAdresse" class="form-control" @bind-Value="@Rechnung.Adresse" />
<ValidationMessage For="@(() => Rechnung.Adresse)" />
</div>
</div>
<SelectedInvoiceLineItems Positionen="@Positionen" OnRemoveItem=@RemoveItem />
<div class="form-group row">
<label>Nettosumme</label>
<label>@Rechnung.NettoSumme</label>
</div>
<div class="form-group row">
<label>zzgl USt</label>
<label>@Rechnung.UStSumme</label>
</div>
<div class="form-group row">
<label>Bruttosumme</label>
<label>@Rechnung.BruttoSumme</label>
</div>
</EditForm>
@*When the modal is here the SaveInvoice-function is not exceuted, but when i place it inside <EditForm> it gets executed*@
@if (EditMode)
{
<button @onclick="ShowModal" class="bg-gray-100 hover:bg-blue-200 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow">Neue Position</button>
}
<div class="form-group row">
<button class="btn btn-success mr-2" @onclick="@OnValidSubmit">
@ButtonText
</button>
<button class="btn btn-secondary" @onclick="@OnCancel">Abbrechen</button>
</div>
@code {
int RechnungID { get; set; }
[Parameter] public Kontakt Kontakt { get; set; }
[Parameter] public Rechnung Rechnung { get; set; }
[Parameter] public List<Artikel> Artikel { get; set; } = new List<Artikel>();
[Parameter] public List<Rechnungsposition> Positionen { get; set; } = new List<Rechnungsposition>();
[Parameter] public string ButtonText { get; set; } = "Speichern";
[Parameter] public EventCallback OnValidSubmit { get; set; }
[Parameter] public EventCallback OnCancel { get; set; }
[Parameter] public EventCallback<Rechnungsposition> OnRemoveItem { get; set; }
[Parameter] public bool EditMode { get; set; }
protected override void OnInitialized()
{
if (!EditMode)
{
Rechnung = new Rechnung();
}
else
{
RechnungID = Rechnung.ID;
}
}
protected override void OnParametersSet()
{
if (!EditMode)
{
Rechnung.Adresse = Kontakt.Name;
Rechnung.KontaktID = Kontakt.ID;
Rechnung.IstBezahlt = false;
}
}
async Task ShowModal()
{
var parameters = new ModalParameters();
parameters.Add(nameof(SelectArticle.Artikel), Artikel);
parameters.Add(nameof(SelectArticle.RechnungID), Rechnung.ID);
parameters.Add(nameof(SelectArticle.Positionen), Positionen);
var options = new ModalOptions()
{
DisableBackgroundCancel = true,
HideCloseButton = true
};
var messageForm = Modal.Show<SelectArticle>("Artikel auswählen", parameters, options);
var result = await messageForm.Result;
if (result.Cancelled)
{
//Console.WriteLine("Modal was cancelled");
}
else
{
//Console.WriteLine($"Anzahl Positionen nach Modal: {Positionen.Count}");
}
}
private async Task RemoveItem(Rechnungsposition pos)
{
await OnRemoveItem.InvokeAsync(pos);
}
}
显示发票行项目和删除可能性的代码:
<div>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Bezeichnung</th>
<th>Anzahl</th>
<th>Stückpreis</th>
<th>Gesamtpreis</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var pos in Positionen)
{
<tr>
<td>@pos.ID</td>
<td>@pos.Bezeichnung</td>
<td>@pos.Anzahl</td>
<td>@pos.Stueckpreis</td>
<td>@pos.Gesamtpreis</td>
<td>
<a class="btn btn-success" href="/invoicelineitem/edit/@pos.ID">Bearbeiten</a>
<button class="btn btn-danger" @onclick="@(() => RemoveItem(pos))">Löschen</button>
</td>
</tr>
}
</tbody>
</table>
</div>
@code {
[Parameter] public List<Rechnungsposition> Positionen { get; set; } = new List<Rechnungsposition>();
[Parameter] public EventCallback<Rechnungsposition> OnRemoveItem { get; set; }
private async Task RemoveItem(Rechnungsposition pos)
{
await OnRemoveItem.InvokeAsync(pos);
}
}
模态代码:
@if (Artikel == null)
{
<text>Lade Daten...</text>
}
else if (Artikel.Count == 0)
{
<text>Keine Daten gefunden.</text>
}
else
{
<table class="table table-sm table-hover table-bordered">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Bezeichnung</th>
<th scope="col">Einheit</th>
<th scope="col">Stückkosten</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach (Artikel art in Artikel)
{
<tr>
<td scope="row"><Input type="checkbox" @onchange="eventArgs => { ArtikelClicked(art, eventArgs.Value); }" /></td>
<td scope="row">@art.Bezeichnung</td>
<td scope="row">@art.Einheit</td>
<td scope="row">@art.Stueckkosten</td>
</tr>
}
</tbody>
</table>
<button @onclick="@Anlegen" class="btn btn-primary">Anlegen</button>
<button @onclick="@Cancel" class="btn btn-secondary">Abbrechen</button>
}
@code
{
[CascadingParameter] BlazoredModalInstance BlazoredModal { get; set; }
[Parameter] public List<Artikel> Artikel { get; set; }
[Parameter] public int RechnungID { get; set; }
private List<Artikel> ArtikelAuswahl = new List<Artikel>();
[Parameter] public List<Rechnungsposition> Positionen { get; set; }
void ArtikelClicked(Artikel artikel, object checkedValue)
{
if ((bool)checkedValue)
{
if (!ArtikelAuswahl.Contains(artikel))
{
ArtikelAuswahl.Add(artikel);
}
}
else
{
if (ArtikelAuswahl.Contains(artikel))
{
ArtikelAuswahl.Remove(artikel);
}
}
}
void Anlegen()
{
Rechnungsposition position;
for (int i = 0; i < ArtikelAuswahl.Count; i++)
{
position = new Rechnungsposition();
position.ID = 0;
position.RechnungID = RechnungID;
position.ArtikelID = ArtikelAuswahl[i].ID;
position.Anzahl = 1;
position.Beschreibung = ArtikelAuswahl[i].Beschreibung;
position.Bezeichnung = ArtikelAuswahl[i].Bezeichnung;
position.Einheit = ArtikelAuswahl[i].Einheit;
position.Stueckpreis = ArtikelAuswahl[i].Stueckkosten;
position.Gesamtpreis = ArtikelAuswahl[i].Stueckkosten;
Positionen.Add(position);
}
BlazoredModal.Close(ModalResult.Ok(true));
}
void Cancel()
{
Console.WriteLine("Cancel");
BlazoredModal.Cancel();
}
}
将按钮类型设置为简单的“按钮”,默认通常是“提交”。
<button type="button" @onclick="ShowModal" ...>Neue Position</button>
Tip: Always specify the type attribute for the element. Different browsers may use different default types for the element.
我是 blazor 的新手,有一个我不明白的问题。
我写了一个简单的测试应用程序,我可以在其中创建联系人、文章和发票。这行得通。在发票中,我可以通过打开模式和 select 一些文章来创建发票行项目,然后获得新的发票行项目。
现在我有两个 problems/questions:
- 当我删除最后一个发票行项目时它有效,但是当我删除另一个而不是最后一个项目时,函数
SaveInvoice
被执行。 - 如果我将模式代码放在
<Editform>
标签内,函数SaveInvoice
也会被执行。如果我将模式放在<Editform>
标签之外,它会按预期工作,但我想将它放在表单内。
为什么没有显式调用就执行了这段代码?我想有某种隐式调用,但我不明白它来自哪里。
你能帮我或给我提示吗?或者您需要更多信息?
发票表单调用代码:
@page "/invoice/edit/{rechnungID:int}"
@inject NavigationManager navMan
@inject IJSRuntime js
@inject IInvoiceRepository invoiceRepository
@inject IArticleRepository articleRepository
<h3>Rechnung bearbeiten</h3>
<FormInvoice ButtonText="Aktualisieren" Artikel="@Artikel" Rechnung="@Rechnung" Positionen="@Positionen" OnValidSubmit="@SaveInvoice" EditMode="true" OnCancel="@Cancel" OnRemoveItem="@RemoveItem" />
@code {
[Parameter] public int rechnungID { get; set; }
Rechnung Rechnung = new Rechnung();
List<Rechnungsposition> Positionen { get; set; } = new List<Rechnungsposition>();
List<Artikel> Artikel { get; set; } = new List<Artikel>();
protected async override Task OnInitializedAsync()
{
Rechnung = await invoiceRepository.GetInvoiceByID(rechnungID);
Positionen = Rechnung.Positionen;
Artikel = await articleRepository.GetArticles();
}
async Task SaveInvoice() // This gets executed and i dont know why
{
await invoiceRepository.UpdateInvoice(Rechnung);
await js.InvokeVoidAsync("alert", $"Erfolgreich aktualisiert!");
navMan.NavigateTo("invoice");
}
void Cancel() => navMan.NavigateTo("invoice");
private void RemoveItem(Rechnungsposition pos)
{
Positionen.Remove(pos);
}
}
发票表格代码:
@inject IModalService Modal
@inject IArticleRepository articleRepository
@inject IInvoiceRepository invoiceRepository
@inject IInvoiceLineItemRepository itemsRepository
<EditForm Model="@Rechnung" OnValidSubmit="@OnValidSubmit">
<DataAnnotationsValidator />
<div class="form-group row">
<label class="col-sm-1 col-form-label" for="inputReNr">Rechnungsnr:</label>
<div class="col-sm-2">
@if (EditMode)
{
<InputText id="inputReNr" class="form-control-plaintext" @bind-Value="@Rechnung.RechnungsNr" readonly />
}
else
{
<InputText id="inputReNr" class="form-control" @bind-Value="@Rechnung.RechnungsNr" />
@*<ValidationMessage For="@(() => Rechnung.RechnungsNr)" />*@
}
</div>
<label class="col-sm-1 col-form-label" for="inputReDatum">Datum:</label>
<div class="col-sm-2">
<InputDate id="inputReDatum" class="form-control" @bind-Value="@Rechnung.RechnungsDatum" />
<ValidationMessage For="@(() => Rechnung.RechnungsDatum)" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-1 col-form-label" for="inputAdresse">Adresse:</label>
<div class="col-sm-5">
<InputTextArea id="inputAdresse" class="form-control" @bind-Value="@Rechnung.Adresse" />
<ValidationMessage For="@(() => Rechnung.Adresse)" />
</div>
</div>
<SelectedInvoiceLineItems Positionen="@Positionen" OnRemoveItem=@RemoveItem />
<div class="form-group row">
<label>Nettosumme</label>
<label>@Rechnung.NettoSumme</label>
</div>
<div class="form-group row">
<label>zzgl USt</label>
<label>@Rechnung.UStSumme</label>
</div>
<div class="form-group row">
<label>Bruttosumme</label>
<label>@Rechnung.BruttoSumme</label>
</div>
</EditForm>
@*When the modal is here the SaveInvoice-function is not exceuted, but when i place it inside <EditForm> it gets executed*@
@if (EditMode)
{
<button @onclick="ShowModal" class="bg-gray-100 hover:bg-blue-200 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow">Neue Position</button>
}
<div class="form-group row">
<button class="btn btn-success mr-2" @onclick="@OnValidSubmit">
@ButtonText
</button>
<button class="btn btn-secondary" @onclick="@OnCancel">Abbrechen</button>
</div>
@code {
int RechnungID { get; set; }
[Parameter] public Kontakt Kontakt { get; set; }
[Parameter] public Rechnung Rechnung { get; set; }
[Parameter] public List<Artikel> Artikel { get; set; } = new List<Artikel>();
[Parameter] public List<Rechnungsposition> Positionen { get; set; } = new List<Rechnungsposition>();
[Parameter] public string ButtonText { get; set; } = "Speichern";
[Parameter] public EventCallback OnValidSubmit { get; set; }
[Parameter] public EventCallback OnCancel { get; set; }
[Parameter] public EventCallback<Rechnungsposition> OnRemoveItem { get; set; }
[Parameter] public bool EditMode { get; set; }
protected override void OnInitialized()
{
if (!EditMode)
{
Rechnung = new Rechnung();
}
else
{
RechnungID = Rechnung.ID;
}
}
protected override void OnParametersSet()
{
if (!EditMode)
{
Rechnung.Adresse = Kontakt.Name;
Rechnung.KontaktID = Kontakt.ID;
Rechnung.IstBezahlt = false;
}
}
async Task ShowModal()
{
var parameters = new ModalParameters();
parameters.Add(nameof(SelectArticle.Artikel), Artikel);
parameters.Add(nameof(SelectArticle.RechnungID), Rechnung.ID);
parameters.Add(nameof(SelectArticle.Positionen), Positionen);
var options = new ModalOptions()
{
DisableBackgroundCancel = true,
HideCloseButton = true
};
var messageForm = Modal.Show<SelectArticle>("Artikel auswählen", parameters, options);
var result = await messageForm.Result;
if (result.Cancelled)
{
//Console.WriteLine("Modal was cancelled");
}
else
{
//Console.WriteLine($"Anzahl Positionen nach Modal: {Positionen.Count}");
}
}
private async Task RemoveItem(Rechnungsposition pos)
{
await OnRemoveItem.InvokeAsync(pos);
}
}
显示发票行项目和删除可能性的代码:
<div>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Bezeichnung</th>
<th>Anzahl</th>
<th>Stückpreis</th>
<th>Gesamtpreis</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var pos in Positionen)
{
<tr>
<td>@pos.ID</td>
<td>@pos.Bezeichnung</td>
<td>@pos.Anzahl</td>
<td>@pos.Stueckpreis</td>
<td>@pos.Gesamtpreis</td>
<td>
<a class="btn btn-success" href="/invoicelineitem/edit/@pos.ID">Bearbeiten</a>
<button class="btn btn-danger" @onclick="@(() => RemoveItem(pos))">Löschen</button>
</td>
</tr>
}
</tbody>
</table>
</div>
@code {
[Parameter] public List<Rechnungsposition> Positionen { get; set; } = new List<Rechnungsposition>();
[Parameter] public EventCallback<Rechnungsposition> OnRemoveItem { get; set; }
private async Task RemoveItem(Rechnungsposition pos)
{
await OnRemoveItem.InvokeAsync(pos);
}
}
模态代码:
@if (Artikel == null)
{
<text>Lade Daten...</text>
}
else if (Artikel.Count == 0)
{
<text>Keine Daten gefunden.</text>
}
else
{
<table class="table table-sm table-hover table-bordered">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Bezeichnung</th>
<th scope="col">Einheit</th>
<th scope="col">Stückkosten</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach (Artikel art in Artikel)
{
<tr>
<td scope="row"><Input type="checkbox" @onchange="eventArgs => { ArtikelClicked(art, eventArgs.Value); }" /></td>
<td scope="row">@art.Bezeichnung</td>
<td scope="row">@art.Einheit</td>
<td scope="row">@art.Stueckkosten</td>
</tr>
}
</tbody>
</table>
<button @onclick="@Anlegen" class="btn btn-primary">Anlegen</button>
<button @onclick="@Cancel" class="btn btn-secondary">Abbrechen</button>
}
@code
{
[CascadingParameter] BlazoredModalInstance BlazoredModal { get; set; }
[Parameter] public List<Artikel> Artikel { get; set; }
[Parameter] public int RechnungID { get; set; }
private List<Artikel> ArtikelAuswahl = new List<Artikel>();
[Parameter] public List<Rechnungsposition> Positionen { get; set; }
void ArtikelClicked(Artikel artikel, object checkedValue)
{
if ((bool)checkedValue)
{
if (!ArtikelAuswahl.Contains(artikel))
{
ArtikelAuswahl.Add(artikel);
}
}
else
{
if (ArtikelAuswahl.Contains(artikel))
{
ArtikelAuswahl.Remove(artikel);
}
}
}
void Anlegen()
{
Rechnungsposition position;
for (int i = 0; i < ArtikelAuswahl.Count; i++)
{
position = new Rechnungsposition();
position.ID = 0;
position.RechnungID = RechnungID;
position.ArtikelID = ArtikelAuswahl[i].ID;
position.Anzahl = 1;
position.Beschreibung = ArtikelAuswahl[i].Beschreibung;
position.Bezeichnung = ArtikelAuswahl[i].Bezeichnung;
position.Einheit = ArtikelAuswahl[i].Einheit;
position.Stueckpreis = ArtikelAuswahl[i].Stueckkosten;
position.Gesamtpreis = ArtikelAuswahl[i].Stueckkosten;
Positionen.Add(position);
}
BlazoredModal.Close(ModalResult.Ok(true));
}
void Cancel()
{
Console.WriteLine("Cancel");
BlazoredModal.Cancel();
}
}
将按钮类型设置为简单的“按钮”,默认通常是“提交”。
<button type="button" @onclick="ShowModal" ...>Neue Position</button>
Tip: Always specify the type attribute for the element. Different browsers may use different default types for the element.