0

I want to add text-boxesdynamically in my MVC add/edit form.

I have a field called 'Interests' and user should be able to add any number of interests he/she likes by clicking on 'Add another' text box.

This, I can do using JQuery.

I want to generate a string which will have comma separated values from the above field 'Interests'.

Suppose user adds three text-boxes with values tennis, football and baseball. I want to combine these values in comma separated string and pass them to Model.Interest which is one of the fields in my User model.

Is there any easy approach to do this..

4
  • 1
    why are you sending comma seperated values to controller. Instead access those values by FormCollection Commented Feb 22, 2013 at 4:13
  • like @DON said, I would assume a list is superior Commented Feb 22, 2013 at 4:14
  • What if your user enters three values tennis, foot,ball, and baseball? Commented Feb 22, 2013 at 4:15
  • Assign text box a name and in controller access it by FormCollection and it will have array values. Check FormCollection Commented Feb 22, 2013 at 4:28

2 Answers 2

3

It much simpler than that, just add a name='' convention to your inputs and the binder of mvc will get the values.

You actually have two options to do so... 1. name="textbox[0].Name" and so on. 2. Create your own Binder, and bind your inputs as you need. You don't have to reinvent nothing.

Excuse me for taking so long to edit my answer, here is the example: The Models:

public class Person
{
    public Person()
    {
        InterestList = new List<Interest>();
    }

    public IList<Interest> InterestList { get; set; }
}

public class Interest
{
    public string Name { get; set; }
}

The Binder:

public class InterestListBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        var person = new Person();
        foreach (var i in controllerContext.RequestContext.HttpContext.Request.Form.AllKeys)
        {
            person.InterestList.Add(new Interest
                {
                    Name = controllerContext.RequestContext.HttpContext.Request.Form[i]
                });
        }
        return person;
    }
}

The Global.asax to attach binder

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        ModelBinders.Binders.Add(typeof(Person), new InterestListBinder());
    }
}

The Controller:

   public class HomeController : Controller
   {
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(Person person)
        {
            return View("Index", person);
        }
    }

And now the view:

@model Data.Services.DataBinders.Person



<div>
    <form action="@Url.Action("Index", "Home")" method="POST">
        @{
            if (Model != null && Model.InterestList.Any())
            {
                foreach (var tb in Model.InterestList)
                {
                    <input type="text" value="@tb.Name"/>
                }
            }
        }
        <input type="button" value="add" id="add" />
        <input type="button" value="remove" id="remove" />
        <input type="submit" value="Submit" />
    </form>
</div>

And the javascript that generates the dynamic inputs, you can put any name you like:

    <script>
    (function ($) {
        var demo = {
            init: function () {
                this.elements = null;
                this.cache();
                this.bindEvents();
                return this;
            },
            cache: function () {
                this.elements = new Array();
            },
            bindEvents: function () {
                $("#add").on("click", this.add);
                $("#remove").on("click", this.remove);
            },
            add: function () {
                var self = demo;
                var $elem = $("<input type='text' \>");
                self.elements.push($elem);
                self.render();
            },
            remove: function () {
                var self = demo;
                $.each(self.elements, function (index, elem) {
                    elem.remove();
                });
                self.elements.splice(0, 1);
                self.render();
            },
            render: function () {
                var self = demo;
                for (var e in self.elements) {
                    self.elements[e].attr("name", "Interest" + e);
                    $("form").append(self.elements[e]);
                }
                console.log(self.elements);
            }
        };
        window.load = demo.init();
    })(jQuery)
</script>
Sign up to request clarification or add additional context in comments.

4 Comments

This is ALSO true. Model Binding like this is a little tricky for new developer. I don't want to assume anything about Marcus25's level of knowledge, but he may need some more guidance.
I actually agree but I'm writing it from my iPhone and can't simulate some code for him
lol!!! I hear you... when you get a chance... I'm off to bed. Yids in NYC sleep now. When you do, LMK so I can vote up...
@DaveA Hey man, i have placed an example you can check it out
2

If all your textboxes shared a class txtInterestsToGrab, you could combine them all into a comma delimited string and post them to a hypothetical action method called saveInterests

    var data = $('.txtInterestsToGrab').val().join(',');



    $.ajax({
        type: "POST",
        url: "/Stuff/saveInterests/",
        dataType: 'json',
        traditional: true,
        data: data,
        success: function () {
        }
    });

if you decide NOT to use a comma delimited string, but instead use a list (which I highly-highly-highly recommend)

    var data = $('.txtInterestsToGrab').val();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.