【问题标题】:Change value of EditorFor on DropDownFor value change在 DropDownFor 值更改时更改 EditorFor 的值
【发布时间】:2016-04-02 19:32:52
【问题描述】:

我正在尝试制作一个在线银行网站(用于学习 ASP.NET MVC)。我有一个类 Account

class Account
{
int account_id;
String account_number;
decimal balance;
}

我有一个交易模型。

 public class MakeTransactionModel
    {
        [Required]
        public String AccountFrom { get; set; }
        [Required]
        public String AccountTo { get; set; }

        public Decimal OrignalBalance { get; set; }
        [Required]
        public Decimal Amount { get; set; }
        [Required]
        public String TransactionFor { get; set; }
    }

然后在控制器中,我将帐户放入 ViewBag。

ViewBag.account_from = new SelectList(db.Accounts, "account_id", "account_number");

在视图中,我创建了一个下拉菜单来显示所有帐户

@Html.DropDownListFor(u => u.AccountFrom, (SelectList)ViewBag.account_from, htmlAttributes: new { @class = "form-control", @id = "AccountFrom", onchange=@"
                    @Model.OrignalBalance = 1000; // I tried this but did not work
                " })

现在,我正在尝试在 EditorFor 中显示 所选帐户余额

@Html.EditorFor(model => model.OrignalBalance, new { htmlAttributes = new { @id="OrignalBalance", @class = "form-control", disabled = "disabled", @readonly = "readonly" } })

我在 ViewBag 中拥有所有帐户,并且我在下拉列表中显示该帐户编号(这些帐户中也有余额)。我正在尝试在 DropDownFor 值更改时更改 EditorFor 的值,但仍然无法做到这一点。我尝试使用 jquery 来做到这一点,但我不知道我可以在 jquery

中使用 LINQ

我的 jquery 代码是

 <script type="text/javascript">

        $(document).ready(function () {
            $(function () {
                $('#AccountFrom').change(function () {
                    var selectedValue = $('#AccountFrom').text();
                    $('#OrignalBalance').val(@{new BankEntities().Accounts.SingleOrDefault(acc => acc.account_number == $('#AccountFrom').text())});   // I am trying to do this
                });
            });
        }
    )
    </script>

如果我能找到一个好的解决方案会很好,这样我就可以在更改事件时更新 EditorFor。

谢谢。

【问题讨论】:

    标签: c# jquery asp.net-mvc linq asp.net-mvc-4


    【解决方案1】:

    您应该进行 ajax 调用并传递帐号并从服务器获取金额。

    $(function()
    {
        $('#AccountFrom').change(function() {
        var accountId= $('#AccountFrom').val();
        var url="@Url.Action("Balance","Account")";
           $.post(url+"?accountNumber="+accountId,function(response){
              if(response.Status==="success")
              {
                $("#OrignalBalance").val(response.Balance);
              }
              else
              {
                 alert("Invalid Account");
              }
           });
        });
    });
    

    假设你有一个返回余额的操作方法

    [HttpPost]
    public ActionResult Balance(string accountNumber)
    {
       //Of course you want to authorize the call
       var db=new BankEntities();
       var a= db.Accounts.FirstOrDefault(x=> x.account_number ==accountNumber);
       if(a!=null)
       {
          return Json( new { Status="success", Balance=a.Balance });
       }
       else
       {
         return Json( new { Status="error"});
       }
    }
    

    如果您不希望创建操作方法和 ajax 方式,您可以做的是,创建一个包含您的帐号和余额的字典,并将其作为您的视图模型和剃刀视图的一部分传递,设置到一个 js 对象,在 change 事件中你可以查询 js 字典来获取值。

    另外,我建议不要使用 ViewBag 在您的操作方法和视图之间传输数据以呈现下拉列表。您应该添加一个强类型属性来处理它。

    让我们为您的视图模型添加一些新属性。

    public class MakeTransactionModel
    {
       // Your other existing properties here
    
       public Dictionary<string,decimal> AccountBalances { set; get; }   
    
       // These 2 properties are for rendering the dropdown.
       public int FromAccountId { set; get; }
       public List<SelectListItem> FromAccounts { set; get; }  
    }
    

    然后在您的 GET 操作中,用帐号和相应的余额值填充此属性。

    public ActionResult Transfer()
    {
      var vm = new MakeTransactionModel();
      vm.AccountBalances = new Dictionary<string, decimal>();
      // Hard coded for demo. You may read it from your db tables.
      vm.AccountBalances.Add("CHECKING0001", 3450.50M);
      vm.AccountBalances.Add("SAVINGS0001", 4450.50M);
    
       //load the data for accounts.pls change to get from db
       vm.FromAccounts = new List<SelectListItem>
       {
           new SelectListItem { Value="CHECKING0001", Text="Checking" },
           new SelectListItem { Value="SAVINGS0001", Text="Saving" }
       };
    
      // to do : Load other properties also
      return View(vm);
    }
    

    然后在你的 razor 视图中,序列化这个属性并设置为一个 js 对象。

    @model MakeTransactionModel
    @using(Html.BeginForm())
    {
      @Html.DropDownListFor(s=>s.FromAccountId,Model.FromAccounts,"Select")
    
      @Html.EditorFor(model => model.OrignalBalance, 
         new { @id="OrignalBalance", @class = "form-control",
         disabled = "disabled", @readonly = "readonly" } )
      <input type="submit" />
    }
    @section Scripts
    {
    <script>   
    var balanceDict = @Html.Raw(Newtonsoft.Json.JsonConvert
                                   .SerializeObject(Model.AccountBalances));
    
    $(function () {
    
        $('#FromAccountId').change(function() {
            var accountId= $('#AccountFrom').val();
            var v = balanceDict[accountId];
            $("#OrignalBalance").val(v);
        });   
    
    });
    </script>
    }
    

    【讨论】:

    • 感谢您的回复。有没有其他方法可以实现这一点。因为我不想创建一个动作方法。
    • 我正在尝试此代码,但 EditorFor 中的文本未更新。我调试代码,它正在发送响应。但现在显示在编辑器中。你能帮我看看这里可能出了什么问题吗?
    • 我在 ajax 调用中有错字。修复。还添加了非 ajax 解决方案。
    • 实际上 jquery 只需将 .html 更改为 .val 即可工作
    【解决方案2】:

    它可能看起来不像,但这相当广泛。基本纲要,你要么必须:

    • 将所有账户和余额序列化为 JSON 并将它们存储在客户端:

      这里的代码比这里合适的要多,但是您可以使用 JSON.net 为 new BankEntities().Accounts.ToList() 获取 JSON(顺便说一下,您应该从控制器代码中获取,而不是在您的视图中),然后设置window 变量添加到您的 JavaScript 中,并在值更改时调用它。

      未经测试,但类似:

      var balances = @Html.Raw(JsonConvert.SerializeObject(new BankEntities()
                                                      .Accounts
                                                      // Filter by logged in user
                                                      .ToDictionary(c => c.account_number, c.balance));
      
      $(document).ready(function () {
          $(function () {
              $('#AccountFrom').change(function () {
                  var selectedValue = $('#AccountFrom').text();
                  $('#OrignalBalance').val(balances[selectedValue]);
              });
          });
      }
      
    • 引入通过 AJAX 执行的 API 调用,以便在值发生变化时获取余额。

      Shyju beat me to this one,但它可能是更好的方法,只要您愿意引入 API 元素。第一次学习 MVC 有点高级,但也不算太复杂。

      这是我在生产应用程序中所做的(尽管我会使用 Web API 来做),但对于只是玩游戏,第一个选项会更快一些,并且如果你完全理解和调试可能更容易刚刚开始。

    这里的混乱来自代码的执行位置。您的script 不能引用BankEntities,因为与服务器端相比,它在客户端运行。

    【讨论】:

    • 感谢您的回复。您认为将信息存储在客户端是否很好。
    • 我也可以在选择列表中使用该序列化对象吗?
    • @WaqarAhmed 两种方法都可以,只是不同而已。 SelectList 是在服务器端构建的,因此您无法访问客户端变量。尽管您可以传递与创建SelectList 相同的列表以进行序列化。在不了解您的代码的情况下,这可能就是我要做的。
    • @WaqarAhmed 我认为您可能需要做一些事情来取消字典 JSON 的转义。我认为@Html 下有些东西,但我已经有一段时间没有对 MVC 做过任何事情了。
    • @WaqarAhmed 找到了;我编辑了我的代码,但您需要将该 JSON 传递给 Html.Raw 以避免它被转义。
    【解决方案3】:

    JQuery 对 LINQ 一无所知,因为它是基于客户端的。因此,我建议在更改帐户时发出 ajax 请求。

    例如,在视图中,进行 ajax 调用

    <script type="text/javascript">
    
        $(document).ready(function() {
    
            $('#AccountFrom').change(function() {
                var selectedAccountNumber = $('#AccountFrom option:selected').text();
                $.ajax({
                    url: "/Accounts/GetAccountBalance",
                    type: "POST",
                    dataType: "json",
                    data: { accountNumber: selectedAccountNumber },
                    success: function (
                        $('#OrignalBalance').val(data.Balance);
                    }
                });
            });
        });
    </script>
    

    并在控制器中包含以下内容(假设您有一个名为 Accounts 的控制器)

    public ActionResult GetAccountBalance(string accountNumber)
    {
        var account = db.Accounts.SingleOrDefault(a => a.account_number == accountNumber);
        // add validation logic for account not exits
    
        return Json(new { AccountNumber = accountNumber, Balance = account.balance });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-24
      • 1970-01-01
      • 2021-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多