2017-06-16 23 views
0

数字だけを受け入れるモデルのプロパティにRegex式を追加しました。動的に追加された要素の検証エラー

public class MaterialsViewModel 
    { 
     [Display(Name = "Material")] 
     public string MaterialName { get; set; } 
     [Range(typeof(int), "0", "999")] 
     [RegularExpression(@"^\d+$", ErrorMessage = "Please enter proper value")] 
     public int? Quantity { get; set; } 
     [RegularExpression(@"^\d+$", ErrorMessage = "Please enter proper value")] 
     public double? Cost { get; set; } 
     public IEnumerable<SelectListItem> CategoryList { get; set; } 

     public int SelectedCategory { get; set; } 
     public string SelectedCategoryName { get; set; } 
    } 

私はここで私がコントロールを追加することができます私の見解を持っている動的

Dynamically add ScopeOfWork and Materials<br /> 
    <div id="scopes"> 
     <h3>Scopes</h3> 
     <a href="javascript:void(0)" id="addScope">Add Scope of Work</a> 
     @for (int i = 0; i < Model.ScopeOfWork.Count; i++) 
     { 
      <div class="scope"> 
       <div class="form-group"> 
        @Html.LabelFor(m => m.ScopeOfWork[i].ScopeOfWorkName, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @Html.TextBoxFor(m => m.ScopeOfWork[i].ScopeOfWorkName, new { @class = "form-control" }) 
         @Html.ValidationMessageFor(m => m.ScopeOfWork[i].ScopeOfWorkName) 
        </div> 
       </div> 
       <input type="hidden" class="scopeindex" name="ScopeOfWork.Index" value="@i" /> 
       <div class="indent materials"> 
        <h4>Material</h4> 
        <a href="javascript:void(0)" class="addmaterial">Add Material</a> 
        @for (int j = 0; j < Model.ScopeOfWork[i].Materials.Count; j++) 
        { 
         <div class="material"> 
          <div class="form-group"> 
           @Html.LabelFor(m => m.ScopeOfWork[i].Materials[j].MaterialName, htmlAttributes: new { @class = "control-label col-md-2" }) 
           <div class="col-md-2"> 
            @Html.TextBoxFor(m => m.ScopeOfWork[i].Materials[j].MaterialName, new { @class = "form-control" }) 
           </div> 
           <div class="col-md-10 col-md-offset-2"> 
            @Html.ValidationMessageFor(m => m.ScopeOfWork[i].Materials[j].MaterialName) 
           </div> 
          </div> 
          <div class="form-group"> 
           @Html.LabelFor(m => m.ScopeOfWork[i].Materials[j].Quantity, htmlAttributes: new { @class = "control-label col-md-2" }) 
           <div class="col-md-1"> 
            @Html.TextBoxFor(m => m.ScopeOfWork[i].Materials[j].Quantity, new { @class = "form-control" }) 
           </div> 
           <div class="col-md-10 col-md-offset-2"> 
            @Html.ValidationMessageFor(m => m.ScopeOfWork[i].Materials[j].Quantity) 
           </div> 
          </div> 
          <div class="form-group"> 
           @Html.LabelFor(m => m.ScopeOfWork[i].Materials[j].Cost, htmlAttributes: new { @class = "control-label col-md-2" }) 
           <div class="col-md-1"> 
            @Html.TextBoxFor(m => m.ScopeOfWork[i].Materials[j].Cost, new { @class = "form-control" }) 
           </div> 
           <div class="col-md-10 col-md-offset-2"> 
            @Html.ValidationMessageFor(m => m.ScopeOfWork[i].Materials[j].Cost) 
           </div> 
          </div> 
          <div class="form-group"> 
           <label class="control-label col-md-2">Category</label> 
           <div class="col-xs-2"> 
            @Html.DropDownListFor(m => m.ScopeOfWork[i].Materials[j].SelectedCategory, Model.ScopeOfWork[i].Materials[j].CategoryList, "Please select", htmlAttributes: new { @class = "form-control" }) 
           </div> 
          </div> 
          <input type="hidden" class="materialindex" name="ScopeOfWork[@i].Materials.Index" value="@j" /> 
         </div> 
        } 
       </div> 
      </div> 
     } 
    </div> 

    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input type="submit" value="Create" class="btn btn-success" /> 
     </div> 
    </div> 
</div> 
} 


<div id="newScope" style="display:none"> 
    <div class="scope"> 
     <div class="form-group"> 
      <label for="_#__ScopeOfWorkName" class="control-label col-md-2">Scope Of Work</label> 
      <div class="col-md-10"> 
       <input class="form-control" type="text" id="_#__ScopeOfWorkName" name="ScopeOfWork[#].ScopeOfWorkName" value=""> 
       <span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].ScopeOfWorkName" data-valmsg-replace="true"></span> 
      </div> 
     </div> 
     <input type="hidden" class="scopeindex" name="ScopeOfWork.Index" value="#" /> 
     <div class="materials"> 
      <h4>Material</h4> 
      <a href="javascript:void(0)" class="addmaterial">Add Material</a> 
     </div> 
     <hr /> 
    </div> 
</div> 

<div id="newMaterial" style="display:none"> 
    <div class="form-group"> 
     <label for="_#__Materials_%__MaterialName" class="control-label col-md-2">Material</label> 
     <div class="col-md-2"> 
      <input class="form-control" type="text" id="_#__Materials_%__MaterialName" name="ScopeOfWork[#].Materials[%].MaterialName" value=""> 
      <span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].Materials[%].MaterialName" data-valmsg-replace="true"></span> 
     </div> 
    </div> 

    <div class="form-group"> 
     <label for="_#__Materials_%__Quantity" class="control-label col-md-2">Quantity</label> 
     <div class="col-md-1"> 
      <input class="form-control" type="text" id="_#__Materials_%__Quantity" name="ScopeOfWork[#].Materials[%].Quantity" value=""> 
      <span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].Materials[%].Quantity" data-valmsg-replace="true"></span> 
     </div> 
    </div> 

    <div class="form-group"> 
     <label for="_#__Materials_%__Cost" class="control-label col-md-2">Cost</label> 
     <div class="col-md-1"> 
      <input class="form-control" type="text" id="_#__Materials_%__Cost" name="ScopeOfWork[#].Materials[%].Cost" value=""> 
      <span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].Materials[%].Cost" data-valmsg-replace="true"></span> 
     </div> 
    </div> 
    @*Drop down*@ 
    <div class="form-group"> 
     <label for="_#__Materials_%__SelectedCategory" class="control-label col-md-2">Category</label> 
     <div class="col-xs-2"> 
      <select class="form-control category" id="_#__Materials_%__SelectedCategory" name="ScopeOfWork[#].Materials[%].SelectedCategory"> 
       <option value="">--Select--</option> 
      </select> 
     </div> 
    </div> 

    <input type="hidden" class="materialindex" name="ScopeOfWork[#].Materials.Index" value="%" /> 
</div> 

<script> 
    var form = $('form'); 
    var scope = $('#newScope'); 
    var material = $('#newMaterial'); 
    var categories = @Html.Raw(Json.Encode(Model.CategoryList)); 

    form.on('click', '.addmaterial', function() { 
     var clone = material.clone(); 
     var scopeIndex = $(this).closest('.scope').find('.scopeindex').val(); 
     clone.html($(clone).html().replace(/#/g, scopeIndex)); 

     var materialIndex = new Date().getTime(); 
     clone.html($(clone).html().replace(/%/g, materialIndex)); 
     // drop down list 
     var select = clone.find('.category'); 
     $.each(categories, function(index, item) { 
      select.append($('<option></option>').val(item.Value).text(item.Text)); 
     }); 
     $(this).closest('.materials').append(clone.html()); 

     form.data('validator', null); 
     $.validator.unobtrusive.parse(form); 
    }); 

    $('#addScope').click(function() { 
     var clone = scope.clone(); 
     var scopeIndex = new Date().getTime(); 
     clone.html($(clone).html().replace(/#/g, scopeIndex)); 
     $('#scopes').append(clone.html()); 
     form.data('validator', null); 
     $.validator.unobtrusive.parse(form); 
    }); 
</script> 

コントローラー:

[HttpPost] 
     public ActionResult _CreateProject(ProjectViewModel project) 
     { 
      tblProject projectModel = new tblProject(); 
      tblScopeOfWork scopeModel = new tblScopeOfWork(); 
      tblMaterial materialModel = new tblMaterial(); 

      if (ModelState.IsValid) 
      { 
       projectModel.ProjectName = project.ProjectName; 
       projectModel.ProjectLocation = project.ProjectLocation; 
       projectModel.ProjectDescription = project.ProjectDescription; 
       projectModel.WorkArea = project.WorkArea; 
       projectModel.ModeOfPayment = project.ModeOfPayment; 
       projectModel.Duration = project.Duration; 
       projectModel.StartDate = project.StartDate; 
       projectModel.EndDate = project.EndDate; 
       projectModel.ProfitSupervision = project.ProfitSupervision; 
       projectModel.ProjectStatus = project.ProjectStatus; 
       projectModel.ForemanId = project.ForemanId; 
       projectModel.ClientId = project.ClientId; 

       db.tblProjects.Add(projectModel); 
       db.SaveChanges(); 

       //Get the recently created ProjectId 
       var recentProjectId = db.tblProjects.OrderByDescending(x => x.ProjectId).FirstOrDefault().ProjectId; 

       //Get all values from List of ScopeOfWork 
       //Add each ScopeOfWork to the database 
       for (int scopeIndex = 0; scopeIndex < project.ScopeOfWork.Count; scopeIndex++) 
       { 
        scopeModel = new tblScopeOfWork(); 
        scopeModel.ScopeOfWork = project.ScopeOfWork[scopeIndex].ScopeOfWorkName; 
        scopeModel.ProjectId = recentProjectId; 

        db.tblScopeOfWorks.Add(scopeModel); 
        db.SaveChanges(); 

        //Get the recently created ScopeOfWorkId 
        var recentScopeOfWorkId = db.tblScopeOfWorks.OrderByDescending(x => x.ScopeOfWorkId).FirstOrDefault().ScopeOfWorkId; 

        //Get all materials from its corresponding ScopeOfWork and save to database 
        for (int materialIndex = 0; materialIndex < project.ScopeOfWork[scopeIndex].Materials.Count; materialIndex++) 
        { 
         materialModel = new tblMaterial(); 
         materialModel.Description = project.ScopeOfWork[scopeIndex].Materials[materialIndex].MaterialName; 
         materialModel.Quantity = project.ScopeOfWork[scopeIndex].Materials[materialIndex].Quantity; 
         materialModel.Cost = project.ScopeOfWork[scopeIndex].Materials[materialIndex].Cost; 
         materialModel.ScopeOfWorkId = recentScopeOfWorkId; 
         materialModel.CategoryId = project.ScopeOfWork[scopeIndex].Materials[materialIndex].SelectedCategory; 
         db.tblMaterials.Add(materialModel); 
        } 
       } 
       db.SaveChanges(); 
      } 

      project.ScopeOfWork = new List<ScopeOfWorkViewModel> 
      { 
       new ScopeOfWorkViewModel() 
       { 
        Materials = new List<MaterialsViewModel> 
        { 
         new MaterialsViewModel() 
         { 
          CategoryList = new SelectList(db.tblCategories, "CategoryId", "CategoryName") 
         } 
        } 
       } 
      }; 
      return View(project); 
     } 
    } 

問題は、私は上のいくつかの文字列( 'SS')を入れてみましたです数量とコストのテキストボックスで検証が有効かどうかを確認すると、The value 'ss' is not valid for QuantityThe value 'ss is not valid for Cost.が表示されますが、それはPlease enter proper valueである必要があります。また、検証が行われるたびに、Add Materialリンクに別のnewMaterialを追加することはできません。

answerと、またDotNetFiddleを試してみましたが、まだ多少の誤差があります。

答えて

1

正規表現は必要ありません(intとにかく数字だけを受け入れることができます)。 costプロパティの場合も同様です(ただし、分数を許可しない場合は10進数にしましたか?)。

タイプの検証が最初に実行され、その無効で、それ以上の検証は実行されないためです。 [Required]

[Range(typeof(int), "0", "999")] 
[Required(ErrorMessage = "Please enter proper value")] 
public int? Quantity { get; set; } 

への

変更属性がtypeのために無効な値のためのデフォルトのエラーメッセージを変更するためにもthis question/answer参照してください。

補足として、必要なdata-val-*属性を追加していないため、動的に追加されたアイテムはクライアント側の検証を行いません。 forループ内の要素に対して生成されたhtmlを調べ、コレクションインデクサーを置き換える以外は、htmlを正確にコピーする必要があります。

ScopeOfWorkプロパティを新しいコレクションに設定し、ビューを返す前にユーザーが入力したすべてのデータを消去するため、POSTメソッドにも問題があります。あなたのPOSTメソッドの基本的な構造はConfigureviewModel()方法はまた、ああ、私は見るが、それでも私は、保存ボタンをクリックしたときに、それが返されますSelectLists

+0

を移入するためにあなたのGETメソッドから呼び出され

[HttpPost] public ActionResult _CreateProject(ProjectViewModel project) { if (!ModelState.IsValid) { ConfigureViewModel(project); return View(project); } // code to initialize your data models, save and redirect } private void ConfigureViewModel(ProjectViewModel model) { var categories = db.tblCategories; model.CategoryList = new SelectList(categories , "CategoryId", "CategoryName"); foreach (var scope in model.ScopeOfWork) { foreach (var material in scope.Materials) { material.CategoryList = new SelectList(categories , "CategoryId", "CategoryName"); } } } 

注意する必要があります私のビューが戻ってきたら、私はもう新しいマテリアルを追加することができませんでしたが、スコープを追加できます。この原因は何ですか? – progammer101

+0

あなたのコードをもっと詳しく調べてください。また、あるタイプのデフォルトメッセージを変更する方法を示すリンクを追加します。 –

+0

また、3つのAdd Materials要素を入力なしで作成しようとしましたが、検証を確認してビューを返すだけでした。1材料要素を追加してください。3 – progammer101

関連する問題