Skrubb
Skrubb

Reputation: 541

Prepopulate HtmlTextBoxFor with value from another field?

I have a web page that is using a number of different partial views and different viewmodels for each partial. One of the partials is for the ability for a user to change their username. Since we are going to allow email addresses as usernames now, I would like to pre-populate the textbox with their current email address from another partial view on the page. How can this be done properly so the value will be populated in the text box and then saved when the submit to the controller happens? Here is a brief code snippet from what I'm looking at:

The view:

@Html.TextBoxFor(model => model.NewUsername, new { id = "uName_change" }) @Html.ValidationMessageFor(model => model.NewUsername)

It's worth noting here that I have tried setting the current email address into ViewData and ViewBag and putting "@value = viewdatahere" into the textbox for properties, but this didn't populate the string, it just left it blank.

I just need to know how this is done. Any help is appreciated.

Edit to add controller POST and GET methods:

[HttpGet]
    [ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
    public ActionResult ChangeUsername(Guid uniqueUserId)
    {
        User user = UserManager.GetUser(uniqueUserId);
        AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, user);
        ChangeUsername model = new ChangeUsername(){UserGuid = user.Identifier,NewUsername = user.Username};
        return View(model);
    }

    [HttpPost]
    [ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
    public ActionResult ChangeUsername(ChangeUsername changeUsername)
    {
        User usr = UserManager.GetUser(changeUsername.UserGuid);
        AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, usr);

        if (!ModelState.IsValid)
        {
            return View(changeUsername);
        }
        //setup request
        SupportUser su = (SupportUser)ViewData["SupportUser"];
        RequestData rqd = new RequestData(GetApplicationIdentifer(usr), su.clientIP, su.lanID);
        UserUsernameChangeRequest request = new AdminUsernameChangeRequest(rqd,usr,changeUsername.NewUsername);

        UserUsernameChangeResponse response = UserManager.ChangeUserUsername(request);

        if (response.Status == UserProcessorStatus.Success)
        {
            var message = ("User has been updated successfully");
            TempData["message"] = message;
            return PartialView("_NewUsername", changeUsername);
        }

        switch (response.Status)
        {
            case UserProcessorStatus.DuplicateUsername:
                {
                    ModelState.AddModelError("NewUsername", "Duplicate username");
                    changeUsername.AlternateUsernames = response.AlternateUsernames;
                    return PartialView(changeUsername);
                }
            default:
                {
                    ModelState.AddModelError("NewUsername", String.Format("An unexpected error occured. Error Code:{0}, Message:{1}", response.Status, response.Message));
                    return PartialView(changeUsername);  
                }
        }


    }

There it is.

Upvotes: 0

Views: 261

Answers (2)

JWP
JWP

Reputation: 6963

Here's how I'd do it.... in the main page set up a viewmodel that contains the other view models like this:

public class VMMain(){
     public void VMMain(){
        //don't forget null CTOR as MVC requires it...
     }
     public void VMMain(Guid userguid, string newusername){
        UserGuid = userguid;
        NewUserName = newusername;
        Part1 = new VM1(UserGuid, NewUserName);
        Part2 = new VM2();
        Part3 = new VM3();
     }
     public VM1 Part1 {get;set;}
     public VM2 Part2 {get;set;}
     public VM3 Part3 {get;set;}
     Guid UserGuid {get;set;}
     string NewUsername {get;set;}
}

In your main view you can bind to anyone of these viewmodels and properties within them. Just make sure you have a property available to bind.

This would change your controller to look like this:

[HttpGet]
[ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
public ActionResult ChangeUsername(Guid uniqueUserId)
{
    User user = UserManager.GetUser(uniqueUserId);
    AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, user);
    var model = new VMMain(){UserGuid = user.Identifier,NewUsername = user.Username};

And now you can bind to say Partial ViewModel 1 that has that property like this:

  @Html.TextBoxFor(p => model.Part1.NewUsername, 
      new { id = "uName_change" })   
  @Html.ValidationMessageFor(p => model.Part1.NewUsername)

    return View(model);
}  

Upvotes: 0

krillgar
krillgar

Reputation: 12815

The last time that I tried to do this was with MVC 3, but I do know that this technique worked then. It's a stupid difference, that's why I pointed that out first.

You were very close with your attempt at it, but you need to set the property as @Value, not @value. I never looked to hard into why the capital made a huge difference. (Like I said, it's a stupid difference.)

var val = "Dummy Value";

@Html.TextBoxFor(model => model.NewUsername, new { id = "uName_change", @Value = val })

Upvotes: 1

Related Questions