How to pass event change to parent from child component - reference

I tried to follow up "Capture references to elements" to pass change to parent from child component and it didn't work url is https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interop?view=aspnetcore-3.0#capture-references-to-elements
Could please help me with?
a) anything wrong in code?
b) where I could find "Console.WriteLine" info since I could not find it from vs output window.
1. ParentComponent.razor
#page "/parentcomponent"
#using BlazorApp.Components
<h1>Parent Component</h1>
<p>ParentYear: #ParentYear</p>
<ChildComponent #ref="ChildComponent1" #bind-Year="ParentYear" />
#code {
private int ParentYear = 1978;
ChildComponent ChildComponent1 = new ChildComponent();
protected override void OnInitialized()
{
ChildComponent1.YearChanged += ChildFiredEvent;
}
public void ChildFiredEvent(int _year)
{
ParentYear = _year;
Console.WriteLine(ParentYear.ToString());
StateHasChanged();
}
}
2. Childcomponent.razor
<h2>Child Component</h2>
<p>ChildYear: #Year</p>
<button class="btn btn-primary" #onclick="ChangeTheYear">Change Year to 1986</button>
#code {
[Parameter]
public int Year { get; set; }
[Parameter]
public Action<int> YearChanged { get; set; }
private void ChangeTheYear()
{
Year = 1986;
YearChanged?.Invoke(Year);
}
}

In the child component, the YearChanged declaration should look like this:
public EventCallBack<int> YearChanged { get; set; }
And then you invoke it like this:
await YearChanged.InvokeAsync(newValue);

Thank you so much, Samer and David. I believe that I used previous blazor methods. Now it works fine with #ref. Cheers!!! here is code.
#page "/parentcomponent"
#using BlazorApp.Components
<h1>Parent Component</h1>
<p>ParentYear: #ParentYear</p>
<ChildComponent #ref="ChildComponent1" #bind-Year="ParentYear" />
#code {
private int ParentYear = 1978;
ChildComponent ChildComponent1 = new ChildComponent();
}
<p>ChildYear: #Year</p>
<button class="btn btn-primary" #onclick="ChangeTheYear">Change Year to 1986</button>
#code {
[Parameter]
public int Year { get; set; }
[Parameter]
public Microsoft.AspNetCore.Components.EventCallback<int> YearChanged { get; set; }
enter code here
private void ChangeTheYear()
{
Year = 1986;
YearChanged.InvokeAsync(Year);
}
}

Related

Blazor creating a generic drop-down

I'm trying to create a generic dropdown component for use across our system. However, I'm encountering issues when binding the EventCallback for when the selected item is changed.
This is my current musings for the generic drop down:
<div class="inputItem #(SizeClass) dropdown" style="min-width:#(Width);">
<SfDropDownList TItem="object" TValue="int" Placeholder="Select a category" DataSource="DataSource" Value="#(SelectedItem)" EnableVirtualization="true">
<DropDownListEvents TItem="object" TValue="int" ValueChange="#OnSelectedItemChanged"></DropDownListEvents>
<DropDownListFieldSettings Text="#(TextField)" Value="#(ValueField)" />
</SfDropDownList>
</div>
#code {
[Parameter]
public IEnumerable<object> DataSource { get; set; }
[Parameter]
public EventCallback<ChangeEventArgs<int, object>> OnSelectedItemChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public string TextField { get; set; }
[Parameter]
public int SelectedItem { get; set; }
[Parameter]
public string ValueField { get; set; }
[Parameter]
public string Width { get; set; }
[Parameter]
public string SizeClass { get; set; }
}
And here's one example component that would call it:
#page "/news/create"
#inject NavigationManager NavManager;
#using Microsoft.EntityFrameworkCore;
#inject IDbContextFactory<FIS2_DbContext> contextFactory;
#inject IFileService fileService;
#using FIS2withSyncfusion.Controls;
#using FIS2withSyncfusion.Models;
#using FIS2withSyncfusion.Utility;
#using Syncfusion.Blazor.RichTextEditor;
#using System.Collections.Generic;
#using System.Threading.Tasks;
#using Newtonsoft.Json;
<div class="dashWrapper">
<SfDashboardLayout AllowDragging="false" AllowFloating="false" AllowResizing="false" CellAspectRatio="2.5" CellSpacing="#(new double[]{20,20})" Columns="3">
<DashboardLayoutPanels>
<DashboardLayoutPanel Column="0" Row="0" SizeX="2" SizeY="2" Id="createNews">
<HeaderTemplate>
<h3>Create A News Item</h3>
</HeaderTemplate>
<ContentTemplate>
<div class="form-wrapper">
<div class="inputRow">
<TextBox AutoComplete="#(Syncfusion.Blazor.Inputs.AutoComplete.Off)" Placeholder="Title" Text="#(title)" HTMLAttributes="#textboxValidation" Width="450px" SizeClass="half-width"></TextBox>
<DropDownList DataSource="categories" Placeholder="Select a category" SizeClass="half-width" Width="450px" TextField="name" ValueField="id" SelectedItem="#(itemModel.Category)" OnSelectedItemChanged="#(OnSelectedItemChanged)"></DropDownList>
#*<SfDropDownList TItem="spGetNewsCategoriesResult" TValue="int" Placeholder="Select a category" #ref="sfDropDown" DataSource="categories" CssClass="inputItem half-width" #bind-Value="#(itemModel.Category)">
<DropDownListFieldSettings Text="name" Value="id" />
</SfDropDownList>*#
</div>
<div class="inputRow">
<CheckBox Checked="isChecked" Label="Suggest Dates This Should Be Active?" OnCheckChange="#(OnCheckChange)" SizeClass="one-third" Width="300px"></CheckBox>
#if (isChecked)
{
<DateTimePicker Label="Active From:" SelectedDate="#activeFrom" Width="450px" SizeClass="one-third"></DateTimePicker>
<DateTimePicker Label="Active To:" SelectedDate="#activeTo" Width="450px" SizeClass="one-third"></DateTimePicker>
}
</div>
<div class="inputRow">
<FileUploader MaxSize="#(MaxSize)" OnClearFiles="OnClearFiles" OnFileRemove="OnFileRemove" OnFileUpload="OnFileUpload" SizeClass="full-width" Width="400px"></FileUploader>
</div>
<RichTextEditor DeniedAttributes="#DeniedAttributes" text=#(itemModel.Content) Height="400px" Width="1600px"></RichTextEditor>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
</div>
#if (ShowDialog)
{
<Dialog Title="Create News Item" message="#Message" OKText="#OKText" cancelText="#CancelText" OnClose="OnDialogClose">
</Dialog>
}
#code {
[CascadingParameter]
Task<AuthenticationState> authenticationStateTask { get; set; }
public string userName { get; set; }
private int MaxSize { get; set; }
private string title { get; set; }
private int selectedCategory { get; set; }
private string content { get; set; }
int count { get; set; }
private bool ShowDialog { get; set; } = false;
private string Message { get; set; } = "";
private string OKText { get; set; } = "";
private string CancelText { get; set; } = "";
public DateTime activeTo { get; set; }
public DateTime activeFrom { get; set; }
private bool isChecked { get; set; }
SaveNewsItemModel itemModel = new SaveNewsItemModel();
List<string> DeniedAttributes = new List<string>() {
"id", "title", "style"
};
Dictionary<string, object> textboxValidation = new Dictionary<string, object>(){
{"maxlength", "100"}
};
List<spGetNewsCategoriesResult> categories = new List<spGetNewsCategoriesResult>();
private async Task OnCheckChange(bool check)
{
isChecked = check;
StateHasChanged();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var authState = await authenticationStateTask;
var user = authState.User;
userName = user.Identity.Name;
var context = contextFactory.CreateDbContext();
var procedures = context.Procedures;
categories = await procedures.spGetNewsCategoriesAsync();
MaxSize = 15 * 1024 * 1024;
}
}
private List<ToolbarItemModel> Tools = new List<ToolbarItemModel>() {
new ToolbarItemModel()
{
Command = ToolbarCommand.Bold
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Italic
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Underline
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Undo
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Redo
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.OrderedList
},
new ToolbarItemModel()
{
Command = ToolbarCommand.UnorderedList
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.FontColor
},
new ToolbarItemModel()
{
Command = ToolbarCommand.CreateLink
},
new ToolbarItemModel()
{
Command = ToolbarCommand.RemoveLink
}
};
private async Task OnFileUpload(UploadChangeEventArgs args)
{
foreach (var file in args.Files)
{
var fileName = file.FileInfo.Name;
using (var ms = file.Stream)
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
int count = 1;
string tempFileName = fileName;
while (fileService.TempFileExists(tempFileName))
{
tempFileName = $"({count}) {fileName}";
count++;
}
var bytes = ms.ToArray();
await fileService.SaveFileToTempAsync(bytes, tempFileName);
var mimetype = fileInfo.Extension;
itemModel.AddFile(fileName, mimetype, tempFileName, contextFactory);
}
}
}
private async Task OnClearFiles(ClearingEventArgs args)
{
foreach (var file in args.FilesData)
{
var fileName = file.Name;
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
itemModel.RemoveFile(fileName, fileInfo.Extension, contextFactory, fileService);
}
}
private async Task OnFileRemove(RemovingEventArgs args)
{
foreach (var file in args.FilesData)
{
var fileName = file.Name;
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
itemModel.RemoveFile(fileName, fileInfo.Extension, contextFactory, fileService);
}
}
private async Task OnSelectedItemChanged(ChangeEventArgs<int, spGetNewsCategoriesResult> eventArgs)
{
itemModel.Category = eventArgs.Value;
StateHasChanged();
}
private async Task OnSave()
{
if (isChecked)
{
itemModel.RequestDates(activeFrom, activeTo);
}
var context = contextFactory.CreateDbContext();
var procedures = context.Procedures;
var addedFiles = await procedures.spCreateNewsItemAsync(JsonConvert.SerializeObject(itemModel), userName);
if (addedFiles.Count > 0)
{
foreach (var file in addedFiles)
{
await fileService.MoveTempToNewsAsync(file.fileName, file.newsID, file.fileID);
}
}
Message = "This has been successfully saved and is now pending review; pressing OK will refresh the page.";
OKText = "OK";
ShowDialog = true;
}
private async Task OnDialogClose(bool r)
{
ShowDialog = false;
NavManager.NavigateTo(NavManager.Uri, true);
}
}
My issue is that I'm getting an error at this point: OnSelectedItemChanged="#(OnSelectedItemChanged)"
The error is:
Cannot convert from method group to EventCallback
The hunting I've done seems to imply that I need to explicitly pass the type in as a parameter, instead of using object and trying to infer it at runtime - I'm just a bit woolly on the details of how to do that?
TValue being an int is something that shouldn't change anywhere. But the TItem could be just about anything (in this particular scenario it's a spGetNewsCategoriesResult) - how do I cater for that?
After much hunting and tinkering, I've found the solution. By changing the component to this:
#typeparam T
<div class="inputItem #(SizeClass) dropdown" style="min-width:#(Width);">
<SfDropDownList TItem="T" TValue="int" Placeholder="Select a category" DataSource="DataSource" Value="#(SelectedItem)" EnableVirtualization="true">
<DropDownListEvents TItem="T" TValue="int" ValueChange="#OnSelectedItemChanged"></DropDownListEvents>
<DropDownListFieldSettings Text="#(TextField)" Value="#(ValueField)" />
</SfDropDownList>
</div>
#code {
[Parameter]
public IEnumerable<T> DataSource { get; set; }
[Parameter]
public EventCallback<Syncfusion.Blazor.DropDowns.ChangeEventArgs<int, T>> OnSelectedItemChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public string TextField { get; set; }
[Parameter]
public int SelectedItem { get; set; }
[Parameter]
public string ValueField { get; set; }
[Parameter]
public string Width { get; set; }
[Parameter]
public string SizeClass { get; set; }
}
And referencing it as such:
<DropDownList DataSource="categories" Placeholder="Select a category" SizeClass="half-width" Width="450px" TextField="name" ValueField="id" SelectedItem="#(itemModel.Category)" OnSelectedItemChanged="#(OnSelectedItemChanged)" T="spGetNewsCategoriesResult"></DropDownList>
The error is resolved. Decided to answer my own question as opposed to just deleting it because I figured it'll probably pop up for people on their own search.

Asp.Net Core: How to properly pass data from view to controller?

I am trying to pass some data from a view to a controller, using a view model.
In view I have something like:
#model LoginRegisterViewModel
<input type="text" name="Email" id="Email" placeholder="Email">
<input type="password" class="form-control" name="Password" id="Password" placeholder="Password">
View Model:
public class LoginModel
{
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Remember Me")]
public bool RememberMe { get; set; }
public string ReturnUrl { get; set; }
}
public class RegisterModel
{
public string Username { get; set; }
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
public string ReturnUrl { get; set; }
}
public class ResetModel
{
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
public string ReturnUrl { get; set; }
}
public class LoginRegisterViewModel
{
public LoginModel Login { get; set; }
public RegisterModel Register { get; set; }
public ResetModel Reset { get; set; }
}
And in controller:
public async Task<IActionResult> Login(LoginRegisterViewModel model, string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var userOrEmail = model.Login.Email;
SignInResult result;
if (userOrEmail.IndexOf('#') > 0)
result = await _signInManager.PasswordEmailSignInAsync(userOrEmail, model.Login.Password, model.Login.RememberMe, false);
else
result = await _signInManager.PasswordSignInAsync(userOrEmail, model.Login.Password, model.Login.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return LocalRedirect(returnUrl);
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
return View(model);
}
I am doing something wrong because I get the following error: NullReferenceException: Object reference not set to an instance of an object.
referencing this line: var userOrEmail = model.Login.Email;
you are binding to the wrong properties.
The controller action expect an object of type LoginRegisterViewModel, and it's the type of the model your view is expecting , but your controls are binding to wrong property .
for example <input type="text" name="Email" id="Email" placeholder="Email"> this maps to model.Email (where model is an object of LoginRegisterViewModel) , and LoginRegisterViewModel doesn't have an Email property but it has a LoginModel property which has the Email property , so you should bind your input to model.Login.Email .
Ps : you can use the MVC core tag helpers to bind properties to model
<input asp-for="model.Login.Email" name="anyothername" class="form-control" />
or even razor syntax
#Html.EditorFor(model => model.Login.Email)
Just got it. I should have used name="Login.Email" and name="Login.Password" in the view.

View not passing data to the controller on submission of form

When I use ViewModel in Create action the data traveled from view to controller but when I use Customer class instead of ViewModel my obj receive no data.
My Customer Model:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSubscribedToNewsletter { get; set; }
public MembershipType MembershipTypes { get; set; }
[Display(Name = "Membership Type")]
public byte MembershiptypeId { get; set; }
public DateTime BirthDate { get; set; }
}
My MembershipType Model:
public class MembershipType
{
public byte Id { get; set; }
public short SignUpFee { get; set; }
public byte DurationInMonths { get; set; }
public byte DiscountRate { get; set; }
public string Name { get; set; }
}
My ViewModel:
public class CustomerViewModel
{
public IEnumerable<MembershipType> MembershipTypes { get; set; }
public Customer Customerss { get; set; }
}
Controller:
[HttpPost]
public ActionResult Create(Customer c)
{
return View();
}
View:
#using (#Html.BeginForm("Create", "Customers"))
{ <div class= "form-group">
#Html.LabelFor(m=> m.Customerss.Name )
#Html.TextBoxFor(m => m.Customerss.Name, new {#class = "form-control"
</div>
<div class="checkbox">
<label>
#Html.CheckBoxFor(m=>m.Customerss.IsSubscribedToNewsletter ) Subscribed To NewsLetter
</label>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Customerss.MembershiptypeId )
#Html.DropDownListFor(m => m.Customerss.MembershiptypeId ,new SelectList(Model.MembershipTypes ,"Id","Name"),"Select Membership Type", new { #class = "form-control" })
</div>
#Html.HiddenFor(m => m.Customerss.Id)
<button type="submit" class="btn btn-primary"> Save </button>}
Page Source

Issue with using a list to populate a table in an MVC 5 View

I have the following code in my controller:
public ActionResult Index(int Id)
{
Landbase _db = new Landbase();
OwnerWorkingInterests workingInterests = new OwnerWorkingInterests();
//Owner owner = new Owner();
var query = (from wg in _db.WorkingInterestGroups
join wi in _db.WorkingInterests on wg.Id equals wi.WorkingInterestGroupId
join l in _db.Leases on wg.LeaseId equals l.Id
where wi.OwnerId.Equals(Id)
select new OwnerWorkingInterests()
{
LeaseId = l.Id,
WorkingInterestAmount = wi.WorkingInterestAmount,
WorkingInterestGroupName = wg.Name,
ClientAlias = l.ClientAlias,
Lessor = l.Lessor,
Lessee = l.Lessee,
VolDocNumber = l.VolumeDocumentNumber,
County = l.County,
District = l.District
}).ToList();
//List<string> OwnerWorkingInterest = query.ToList<string>();
return View(query);
}
I have the following code in my view:
<div id="OwnerWorkingInterests" class="tab-pane fade">
<h3>Working Interests</h3>
<table class="table">
<thead>
<tr>
<td>Lease Id:</td>
<td>Working Int:</td>
<td>WI Group Name:</td>
<td>Alias:</td>
<td>Lessor:</td>
<td>Lessee:</td>
<td>VolPg:</td>
<td>County:</td>
<td>District0:</td>
</tr>
</thead>
<tbody>
#foreach (var owi in OwnerWorkingInterests)
{
<tr>
<td>#owi.LeaseId</td>
<td>#owi.WorkingInterestAmount</td>
<td>#owi.WorkingInterestGroupName</td>
<td>#owi.ClientAlias</td>
<td>#owi.Lessor</td>
<td>#owi.Lessee</td>
<td>#owi.VolDocNumber</td>
<td>#owi.County</td>
<td>#owi.District</td>
</tr>
}
</tbody>
</table>
</div>
I thought this would populate the table with the proper information
This is the viewmodel:
namespace LandPortal.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
public partial class WorkingInterest
{
public int Id { get; set; }
public int? OwnerId { get; set; }
[Column("WorkingInterest")]
public decimal? WorkingInterestAmount { get; set; }
[StringLength(45)]
public string CreateUser { get; set; }
[StringLength(45)]
public string ModifyUser { get; set; }
public Guid? CreateUserId { get; set; }
public Guid? ModifyUserId { get; set; }
public DateTime? CreateDate { get; set; }
public DateTime? ModifyDate { get; set; }
public int? WorkingInterestGroupId { get; set; }
public WorkingInterestGroup WorkingInterestGroup { get; set; }
public decimal? ORRI { get; set; }
public int? ORRIOwnerId { get; set; }
public virtual Owner Owner { get; set; }
}
}
So what happens is it throws a very vague error when I run it in debugger. It literally just says Error: An error occurred when processing your request. So I am assuming that the list is populating but not working in the foreach in the view. I could be wrong at this point.
Here are the model directives for the view
#using LandPortal.Models
#using LandPortal.ViewModels
#using Microsoft.Ajax.Utilities
#model LandPortal.Models.Owner
If the view expects a model that is of type LandPortal.Models.Owner, and Index returns an entire ActionResult, then Index needs to return a model of that type.
A tiny example:
public ActionResult Index(int Id)
{
Landbase _db = new Landbase();
Owner owner = new Owner();
// some query has to set properties on this owner object
// let's pretend there's a property named OwnerWorkingInterests on it
owner.OwnerWorkingInterests = query.ToList(); // you will have to define "query" and set it similar to how you already did
return View(owner);
}
Now your view can access the property on the model as so
#foreach (var owi in Model.OwnerWorkingInterests)
This is a very high level example, but I see you have a partial class and mentioned partial views in your comment. If you have a large view and are trying to break up a query into pieces, that can be done with PartialViewResult and will be a bit different from this.

Populating a select box in a form using related ID in MVC3

I have a very simple data structure with two models. The first containing UserName, UserQuestion and userLocationID and another with LocationName and LocationID, the locationID in the first table is related to the LocationName the second table. However I've not specified any relationship. I've set up the data structure using the code first method in used here .
I would like to create a form which has two text inputs for a user to enter their name and question and a select box that is populated with all the locationNames from the second table. However I can't seem to create the model that allows me to do so. Do I need to make a separate ViewModel?
Does anyone know of a simple tutorial that will explain how to do this?
I'm quite new at MVC, and the dot net framework. . And I've had a look at this answer but I can't seem to modify it to fit my needs. So Apologies if I'm asking for something really basic.
I can give an example in one controller, one view and three C# classes. To use this code, create an empty MVC2 project in visual studio and add a reference to Entity Framework dll version 4.1. If you need help as to where to put these files I recommend Steve Sanderson's MVC2 book.
public class User
{
public int ID { get; set; }
public string UserName { get; set; }
public string Question { get; set; }
public virtual Location Category { get; set; }
}
public class Location
{
public int ID { get; set; }
public string LocationName { get; set; }
}
Repository
using System.Data.Entity;
using System.Collections.Generic;
using System.Linq;
public class Repository : System.Data.Entity.DbContext
{
public DbSet<User> User { get; set; }
public DbSet<Location> Locations { get; set; }
public Repository()
{
this.Database.Connection.ConnectionString =
#"Server=.;Database=Test;Integrated Security=SSPI";
if (!this.Database.Exists())
{
this.Database.Create();
this.Locations.Add(new Location { LocationName = "Queensway" });
this.Locations.Add(new Location { LocationName = "Shepherds Bush" });
this.SaveChanges();
}
}
public IEnumerable<Location> GetLocations()
{
return this.Locations.Where(x => x.ID > -1);
}
public Location GetLocation(int id)
{
return this.Locations.First(x => x.ID == id);
}
public void SaveUser(User user)
{
this.User.Add(user);
this.SaveChanges();
}
}
Controllers\HomeContoller.cs:
using System.Web.Mvc;
public class HomeController : Controller
{
Repository repo = new Repository();
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(User user, int categoryId)
{
user.Category = repo.GetLocation(categoryId);
repo.SaveUser(user);
return View();
}
}
Views\Home\Index.aspx
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<User>" %>
<html>
<body>
<% using (Html.BeginForm())
{%>
Username: <%: Html.TextBoxFor(model => model.UserName) %><br />
Question: <%: Html.TextBoxFor(model => model.Question) %><br />
Location: <select name="categoryId">
<% foreach (var location in new Repository().GetLocations())
{%>
<option value="<%= location.ID %>">
<%= location.LocationName %></option>
<%} %>
<br />
</select>
<p>
<input type="submit" value="Create" />
</p>
<% } %>
</body>
</html>

Resources