Reputation: 372
I am creating a form to put data in a database. Now I want to use an array, because I want to put a form, inside a form. For example, you have a form where a user puts information about himself, like age name and so on. One question is about his friends, you must fill in the name and age off all your friends. Because you have more then one friend, you can add more than one friend. So you fill in the name and age of one friend, click on save, and then you can continue fill in the info of another friend. When you click save, you don't save the whole form.
I hope this I explaned it well.
This is my form:
public class User
{
[BsonElement("Id")]
public int Id { get; set; }
[BsonElement("Email")]
public string Email { get; set; }
[BsonElement("Name")]
public string Name{ get; set; }
[BsonElement("Company")]
public string Company { get; set; }
[BsonElement("Array friends")]
}
View:
@model ISPInvoice.Models.Invoice
@using (Html.BeginForm("Edit", "Home"))
{
@Html.ValidationSummary(true)
<fieldset>
<legend>New Note</legend>
<h3>New Note</h3>
<div class="editor-label">
@Html.LabelFor(model => model.InvoiceNumber)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.InvoiceNumber)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Upvotes: 0
Views: 6256
Reputation: 13286
It sounds like you'll need some client-side code.
What I'd probably do, as I understand your need, would be to have a hidden input in the form that you update with the friends that have been selected.
The trouble is that standard form encoding doesn't support hierarchical data, so you need to add support for that manually. That's not too hard, as you'll see, but it's a hassle. This would be super easy if you were using a framework like Angular, or even just posting with AJAX in general. But that's a pretty big change, that might not be worth going through and implementing just for this case.
This example depends on jQuery. It's also super simple, and doesn't support anything like removal or editing of existing friends. You should be able to add that stuff pretty easily, though. It also does absolutely no validation on anything, so take that how you will.
var friends = [];
function refreshHiddenField() {
$("#friendsListText").val(friends.map(function(d) { return d.name + "=" + d.age }).join(";"));
}
document.addEventListener("DOMContentLoaded", function(event) {
$("#btnAddFriend").click(function() {
var name = $("#newFriendName").val();
var age = $("#newFriendAge").val();
friends.push({ name : name, age: age });
refreshHiddenField();
var li = $("<li />").text(name + " (" + age + ")");
$("#friendsList").append(li);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- This will actually be an @Html.HiddenFor(m => m.FriendsText), or something -->
<input type="text" id="friendsListText" readonly placeholder="Add some friends first" />
<hr />
<input type="text" id="newFriendName" placeholder="Name" />
<input type="number" id="newFriendAge" placeholder="Age" />
<button type="button" id="btnAddFriend">Add!</button>
<br />
<ul id="friendsList">
</ul>
As you'll find playing with that (albeit very lightly tested) example, adding a friend appends the details to a user-visible list, and appends a machine-readable format into an input. Per the comment, this input is visible in this example to see what's happening, but it wouldn't be in production.
Once you've got your client-side code done, you just have to parse the hidden field on save. Assuming a Friend
class with properties for string Name
and int Age
,
[HttpPost]
public ActionResult EditProfile(User m)
{
// Unrelated stuff
var friends = m.FriendsText.Split(';').Select(c => {
var args = c.Split('=');
return new Friend { Name = args[0], Age = int.Parse(args[1]) };
})
// Use the collection
// Unrelated stuff
}
This is just some pretty simple string manipulation with LINQ and the Split
function to understand the machine-readable format from the client.
Note with this implementation that names can't have semicolons or equals signs in them.
Once you've got it all in, printing it out is easy. Just, yes, add a collection type to your model, then loop through with a foreach
loop.
<ul>
@foreach (var f in Model.FriendsCollection)
{
<li>@f.Name (@f.Age)</li>
}
</ul>
I know that's not what you're talking about, but I offer this just as an example of how you would include a collection in the model, per your original question.
Upvotes: 2
Reputation: 5771
Add another class called Friend
public class Friend
{
[BsonElement("Name")]
public string Name { get; set; }
[BsonElement("Age")]
public int Age{ get; set; }
}
In your User class add a List of Friends.
public class User
{
[BsonElement("Id")]
public int Id { get; set; }
[BsonElement("Email")]
public string Email { get; set; }
[BsonElement("Name")]
public string Name{ get; set; }
[BsonElement("Company")]
public string Company { get; set; }
[BsonElement("Array friends")]
public List<Friend> Friends { get;set;}
}
In order to access the Friends list inside the View, you can loop through the list.
@foreach (namespace.Models.Friend friend in Model.Friends)
{
@Html.LabelFor(item => friend.Name)
}
Upvotes: 3