How can i use the value from a textbox component in blazor? - razor

Im trying to create a textbox component to recicle code, but i cant get the value from the textbox in a page. I only need to get the TextBox value from the component to use it into other pages.
this is the TextBox component :
<style>
.textbox-parameters{
background: Red;
}
</style>
#if (!string.IsNullOrWhiteSpace(Label))
{
<label for="#Id">#Label</label>
}
<div class="input-group mb-3 " >
<input type="text" class="form-control textbox-parameters" id="#Id" #bind="#CurrentValue">
</div>
#code {
[Parameter] public string? Label { get; set; }
[Parameter] public string? Id { get; set; }
private string CurrentValue {get;set;} = "";
}
and im trying to use there:
<div class="container-fluid">
<div class="row">
<div class="col-sm">
<label >Proyecto:</label>
<div class="input-group mb-3">
<input type="text" class="form-control" id="basic-url" aria-describedby="basic-addon3">
</div>
</div>
<div class="col-sm">
<p class="rcorners2">Lista modelos</p>
</div>
<div class="col-sm">
<p class="rcorners2">Lista Iteraciónes</p>
</div>
<div class="col-sm">
<p class="rcorners2">Imagen Semilla</p>
</div>
<div class="col-sm ">
<div class="row">
<div class="col-sm">
<label>Ancho</label>
<div class="input-group mb-3">
<div class="input-group-prepend"></div>
<input type="text" class="form-control textbox-parameters" id="basic-url" aria-describedby="basic-addon3">
</div>
</div>
<div class="col-sm">
<TextBox Id="Alto" Label="Alto" CurrentValue="#alto" />
</div>
<label>Texto: #alto</label>
</div>
<div class="row">
<div class="col-sm text-center">
<label>Numero Imágenes</label>
<div class="input-group mb-3 " >
<input type="text" class="form-control textbox-parameters" id="basic-url" aria-describedby="basic-addon3">
</div>
</div>
</div>
</div>
<div class="col-sm">
<button type="button" class="btn btn-outline-success">Generar</button>
</div>
</div>
</div>
#code{
string alto="";
}
Sorry for my extra text but StackOverflow need more details but thats my only problem with my code. thanks.

You need to set up binding correctly - i.e. set up the Value and ValueChanged parameters on the component.
Here's TextBox:
<style>
.textbox-parameters{
background: Red;
}
</style>
#if (!string.IsNullOrWhiteSpace(Label))
{
<label for="#Id">#Label</label>
}
<div class="input-group mb-3 " >
<input type="text" class="form-control textbox-parameters" id="#Id" value="#Value" #onchange="this.OnChange">
</div>
#code {
[Parameter] public string Value {get;set;} = "";
[Parameter] public EventCallback<string> ValueChanged {get;set;}
[Parameter] public string? Label { get; set; }
[Parameter] public string? Id { get; set; }
private void OnChange(ChangeEventArgs e)
{
ValueChanged.InvokeAsync(e.Value.ToString());
}
}
Note we've bound the value to Value and the change event to OnChange which then invokes ValueChanged.
And a test page:
#page "/"
<TextBox #bind-Value="#this.Value" />
<div>
Value = #this.Value
</div>
#code {
private string Value { get; set; } = "Fred";
}
#bind-Value tells the Razor pre-compiler to bind to Value to set the value and ValueChanged to update the bound field/property.

Related

An expression tree may not contain a dynamic operation -mvc

I use two model in a single view so for that i make a class in i which I put both model.But when i use it, it gives me error.
Model:
namespace Laboratory_Management.Models
{
public class PatientandTest
{
public PatientTbl PatientTbl { get; set; }
public PatientTestTbl PatientTestTbl { get; set; }
}
}
View:
#model Laboratory_Management.Models.PatientandTest
#{
ViewData["Title"] = "Index1";
}
<h1>Index1</h1>
<h4>PatientTbl</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Index1" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="PatientTbl.PName" class="control-label"></label>
<input asp-for="PatientTbl.PName" class="form-control" id="PName" />
<span asp-validation-for="PatientTbl.PName" class="text-danger"></span>
</div>
</form>
</div>
</div>

Dropdown validation for default value

I need help on how to validate the default value on a select dropdown list. What I have now doesn't show the validation on the view because I have '--Select--' as the first value. What can I do to get the validation to work. It works for Order, Title, URL but not for the select dropdown. I added a value = "0" and added Range attribute in view model.
Edit: I have to change this so it uses validation summary instead of using the tags for each field but I still can't get the validation messages to show.
<form id="form-create-link" method="post" asp-controller="Link"
asp-action="CreateLink">
<div class="form-group col-md-8">
**<div asp-validation-summary="ModelOnly" id="validation-error" hidden
class="text-danger custom-validation-summary"></div>
</div>**
<input id="link-id" asp-for="#Model.LinkId" type="hidden" />
<input name="FetchCategories" type="hidden"/>
<div class="form-group col-md-8 col-lg-4">
<div class="form-group">
#{
var authorizedCommitteeTypes = await Model.CommitteeType
.ToSelectListAsync(AuthorizationService, User,
AuthRequirements.AdminCommitteeType);
if (authorizedCommitteeTypes.Count == 1)
{
<input id="committeeType" name="committeeType" type="hidden"
value="#authorizedCommitteeTypes.FirstOrDefault()?.Value" />
}
else
{
<label class="control-label">Committee Type</label>
<select id="add-edit-committee-type"
name="committeeType"
asp-for="#Model.CommitteeType"
asp-items="#authorizedCommitteeTypes"
class="form-control">
</select>
}
}
</div>
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">Category</label>
#{
if (Model != null && Model.AvailableCategories != null)
{
var availableCategories =
new SelectList(
Model.AvailableCategories.OrderBy(c => c.Order),
dataValueField: "CategoryId",
dataTextField: "Title",
selectedValue: Model.CategoryId);
<select id="dropdown-linkCategories" required
asp-for="#Model.CategoryId"
asp-items="#availableCategories"
class="form-control">
<option>-- Select --</option>
</select>
}
else
{
<select id="dropdown-linkCategories"
class="form-control">
<option>-- Select --</option>
</select>
}
}
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">Title</label>
<input id="title" asp-for="Title" name="Title" class="form-control" />
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">Display Order</label>
<div>
<input id="order" asp-for="Order" name="Order" class="form-control" />
</div>
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">URL</label>
<input id="url" asp-for="URL" name="URL" class="form-control" />
</div>
<div class="form-group col-md-8 col-lg-12">
<label class="control-label">Description</label>
<textarea class="rtextDescription" name="Description" id="Description"
row="1" cols="60"
data-val-maxlength-max="200" asp-for="Description"
data-val-maxlength="Max length for Description is 200"></textarea>
</div>
<div class="form-group col-md-8 col-lg-12">
<label class="check " >
Add Another
<input type="checkbox" name="AddAnother">
<span class="checkmark"></span>
</label>
</div>
#{
if (Model.LinkId == 0)
{
<div class="form-group col-md-12">
<input type="submit" id="link-submit"
class="btn btn-forum col-sm-12 col-md-4 col-lg-4"
value="Add & Return to Links" />
<a asp-area="Admin"
asp-controller="Link"
asp-action="Index"
class="btn btn-forum col-sm-12 col-md-2 col-lg-2">Back to
Links</a>
</div>
}
else
{
<div class="form-group col-md-8 col-lg-12">
<input type="submit" value="Save" id="edit-submit"
class="btn btn-forum col-sm-12 col-md-2 col-lg-2" />
<a asp-area="Admin"
asp-controller="Link"
asp-action="Index"
class="btn btn-forum col-sm-12 col-md-2 col-lg-2">Back to
Links</a>
</div>
}
}
</form>
According to your code, it seems that the View Model contains the selected properties (such as: CommitteeType, CategoryId), after selecting item from the DropDownlist, we could get the selected value from these properties. So, to validate the DropDownList, we could add the validate attribute to these selected properties.
You could refer the following sample, it will create a custom validation attribute to check whether the selected value is valid or not:
Models:
public class Categories
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}
public class Order
{
[Required]
public int OrderId { get; set; }
[Required]
public string Title { get; set; }
[CheckSelctedValue(ErrorMessage ="Please select a valid category")]
public string CategoryId { get; set; } //DropDownList selected value
public List<Categories> AvailableCategories { get; set; } //DropDownList select items.
}
Here, create a custom validation attribute to check whether the selected value is valid or not.
public class CheckSelctedValue : ValidationAttribute
{
public override bool IsValid(object value)
{
int number;
//get the selected value and according to the condition to check whether the value is valid or not.
//try to convert the selected value to int.
bool success = int.TryParse(value.ToString(), out number);
//if the number is 0, it means user select the first item.
if (success && number !=0)
{
return true;
}
else
{
return false;
}
}
}
Controller:
public IActionResult CreateOrder()
{
Order o = new Order();
o.OrderId = 1001;
o.Title = "AA";
o.AvailableCategories = new List<Categories>()
{
new Categories(){ CategoryID=101, CategoryName="Meat"},
new Categories(){ CategoryID=102, CategoryName="Fruit"},
new Categories(){ CategoryID=102, CategoryName="Vegetables"}
};
o.CategoryId = "101";
return View(o);
}
[HttpPost]
public IActionResult CreateOrder(Order order)
{
//used to set the select items for the dropdownlist.
order.AvailableCategories = new List<Categories>()
{
new Categories(){ CategoryID=101, CategoryName="Meat"},
new Categories(){ CategoryID=102, CategoryName="Fruit"},
new Categories(){ CategoryID=102, CategoryName="Vegetables"}
};
if (ModelState.IsValid)
{
}
return View(order);
}
Code in the View Page (add value="0" to the dropdownlist first option):
#model netcore5.Models.Order
<div class="row">
<div class="col-md-4">
<form asp-action="CreateOrder">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="OrderId" class="control-label"></label>
<input asp-for="OrderId" class="form-control" />
<span asp-validation-for="OrderId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CategoryId" class="control-label"></label>
<select id="dropdown-linkCategories" required
asp-for="CategoryId"
asp-items="#(new SelectList(Model.AvailableCategories, "CategoryID","CategoryName", Model.CategoryId))"
class="form-control">
<option value="0">-- Select --</option>
</select>
<span asp-validation-for="CategoryId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
The output as below:
Edit
I updated my code. I have to use the validation summary that is at the
top of the form but I can't get the validation messages to show.
<div asp-validation-summary="ModelOnly" id="validation-error" hidden class="text-danger custom-validation-summary"></div>
The issue is related to the above code.
First, if we want to show the validation message summary, we should set the asp-validation-summary attribute to All, instead of ModelOnly. More detail information, see The Validation Summary Tag Helper.
Second, since you are using hidden attribute, it will hide the validation message, so, try to remove the hidden attribute.
After updated, the code should be as below:
<div asp-validation-summary="All" id="validation-error"
class="text-danger custom-validation-summary"></div>

Angular validations showing during the page load

We are working on the Angular 4 form and set some validations on the input field but the validation is showing when the page load's but we want the validation when the form is submitted or the field is not valid or filled.
Component.html
<div class="headerbutton-group row">
<i class="fa fa-save header-buttons" tooltip ="Save" tabindex="1" (click)="onSave($event)"></i>
<i class="fa fa-close header-buttons" tooltip ="Close" (click)="onCancel($event)"></i>
</div>
<form [formGroup]="editForm" class="col-md-12 ">
<div class="form-group row">
<div class="col-md-6 padding-Mini">
<label class="col-md-12 col-form-label padding-bottom-Mini" for="txtName">Name</label>
<div class="col-md-12">
<input type="text" id="txtName" name="txtName" class="form-control" placeholder="Name" formControlName="name" [class.is-invalid]="!editForm.controls.name.valid" [class.is-valid]="editForm.controls.name.valid" required>
<div class="invalid-feedback" [style.visibility]=
"editForm.controls.name.valid ? 'hidden':'visible'"> Name is required</div>
</div>
</div>
<div class="col-md-6 padding-Mini">
<label class="col-md-12 col-form-label padding-bottom-Mini" for="txtName">Description</label>
<div class="col-md-12">
<input type="text" id="txtDescription" name="txtDescription" class="form-control"
placeholder="Description" formControlName="description">
</div>
</div>
</div>
</form>
Component.ts
#Component({
selector: 'app-edit-form',
templateUrl: './component.html'
})
export class LoginFormComponent implements OnInit {
constructor(fb:FormBuilder) {
public editForm: FormGroup = new FormGroup({
name : new FormControl('', Validators.required),
description : new FormControl(''),
});
}
public onSave(e): void {
if (this.editForm.valid) {
e.preventDefault();
this.save.emit(this.editForm.value);
} else {
this.validateAllFormFields(this.editForm);
}
}
public onCancel(e): void {
e.preventDefault();
this.closeForm();
}
private validateAllFormFields(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateAllFormFields(control);
}
});
}
}
// Tried this too editForm.controls.name.pristine
We don't know what we are missing. Kindly help us, with useful documents/ Demo's.
try changing this
<div class="invalid-feedback" [style.visibility]="editForm.controls.name.valid ? 'hidden':'visible'">
Name is required
</div>
to this
<div class="invalid-feedback" *ngIf="!editForm.controls.name.valid && editForm.controls.name.touched">
Name is required
</div>
adding a test on "touched" will fix your problem !

How to pass button value from a modal window (that uses partial view) to the parent view

here is the button on the partial view,
<button type="button" name="btnid" id="bparentid" value="#item.Itemid " class="btn btn-success" onclick="alert(#item.Itemid)">Select</button>
Just to check if it holds the value I put razor alert function, and I want the button value to be passed to the parent view on button click using this hidden input form in the parent view
<input asp-for="Itemid" type="hidden" value=" #item.Itemid" />
More detail:
I have two tables for recording children and their parents separately,
Here is the Model
public class Children
{
[Key]
public int ChildID { get; set; }
[Required] [StringLength(50)]
public string FirstName { get; set; }
[ForeignKey("Parentid")]
public virtual Parent Parent { get; set; }
}
public class Parent
{
[Key]
public int Parentid { get; set; }
public string FullName { get; set; }
public virtual IEnumerable<Children> Children { get; set; }
}
And here is the Create method controller for posting new children record with their parent information:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ChildID,FirstName")] Children children, int existingParentid,
[Bind("Parentid,FullName")] Parent parent, bool existingparent)
{
if (ModelState.IsValid)
{
if (existingparent)
{
children.Parentid = existingParentid;
_context.Add(children);
await _context.SaveChangesAsync();
return View(children);
}else
_context.Add(children);
await _context.SaveChangesAsync();
_context.Add(parent);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(children);
}
Here is the controller method for the modal partial view
public async Task<IActionResult> ModalAction()
{
var MyDbContext = _context.Children.Include(C => C.Parent);
return PartialView(await MyDbContext.ToListAsync());
}
And here is the view for the Create method
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="FirstName" class="control-label"></label>
<input asp-for="FirstName" class="form-control" />
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
#Html.ActionLink("Select Existing Parent", "ModalAction", "Children", null, new { #class = "btn btn-flat margin",
data_target = "#searchparent", data_toggle = "modal" })
<input asp-for="Parentid" type="hidden" value=" " />
<div class="modal fade" id="searchparent">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Parent.FullName" class="control-label"></label>
<input asp-for="Parent.FullName" class="form-control" />
<span asp-validation-for="Parent.FullName" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
Here is the modal partial view
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Search for Parent data table </h4>
</div>
<div class="modal-body">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
<button type="button" name="bparentid" id="bparentid" value="#item.ChildID" class="btn btn-block btn-success btn-xs"
onclick="alert(#item.ChildID)">
Select
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
The Question:
How can I pass the #item.ChildID value from the partial view to the Create view which will then pass it as hidden value to the create controller
Since you are trying to change the value of the input field after the page has loaded, this needs to happen inside the user's browser, so Razor which runs server-side can't help. But you can accomplish what you want using javascript:
//First add an ID to your hidden input
<input id="my-input" ... />
//Second add the following onclick to your button:
<button onclick="document.getElementById('my-input').value = this.value" ...></button>

I am trying to form relationship for models between News and its Category

I want to have News can have multiple NewsCategories. one-to-many relationship. I am trying to pass categories to MVC controller (post create action). But ModelState.IsValid is always failed. I think my post action does not get selected values from view somehow..
Please help my friend geeks!
I have News.cs:
public class News
{
public long NewsId { get; set; }
public ICollection<NewsCategory> NewsCategories { get; set; }
}
I have NewsCategory.cs:
public class NewsCategory
{
public int NewsCategoryId { get; set; }
public long NewsId { get; set; }
public string Title { get; set; }
}
I have NewsController.cs:
// GET: News/Create
public IActionResult Create()
{
List<NewsCategory> newsCategories = new List<NewsCategory>();
newsCategories = (from s in _context.NewsCategory select s).OrderBy(m => m.Title).ToList();
newsCategories.Insert(0, new NewsCategory { NewsCategoryId = 0, Title = "Select" });
ViewBag.NewsCategories = newsCategories;
return View();
}
And this is Create Post action:
// POST: News/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Title,Content,NewsTagName1,NewsTagName2")]News news, List<IFormFile> files)
{
if (ModelState.IsValid)
{
_context.Add(news);
var newsCategories = news.NewsCategories;
foreach(var item in newsCategories)
{
item.NewsId = news.NewsId;
_context.NewsCategory.Add(item);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(news);
}
But always fails on 'Model.IsValid'
Here is snapshot of what's in object News.
Here is the error message:
Here is News create view:
#model Carsubfax.Models.News
#{
ViewData["Title"] = "Create";
}
<form asp-action="Create" id="comment-form" name="comment-form" method="post" enctype="multipart/form-data">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" id="txtTitle" autocomplete="off" required="required" placeholder="Enter your news title." />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
</div>
<div class="col-md-10 col-md-offset-1">
<div class="form-group">
<label class="control-label">News Cover Image<span style="color:red">*</span></label>
<input type="file" name="files" required />
</div>
</div>
<div class="col-md-10 col-md-offset-1">
<div class="form-group">
<label class="control-label">News Category</label>
<select asp-for="NewsCategories" class="form-control" asp-items="#(new SelectList(ViewBag.NewsCategories, "NewsCategoryId", "Title"))" required="required"></select>
</div>
<div class="col-md-10 col-md-offset-1">
<div class="form-group text-center">
<button type="submit" class="btn btn-primary" onclick="return btnSubmit_clik();">POST</button>
</div>
</div>
<div class="col-md-10 col-md-offset-1">
<div class="form-group text-center">
<a asp-action="Index">Back to List</a>
</div>
</div>
</div>
</form>
</div>
</div>