私もまったく同じ状況に対処しなければなりませんでした。私が思いついた最も簡単な解決策は、次のようなラッパーモデルを使用することでした。
public class QuestionListModel
{
public IList<QuestionModel> Questions { get; set; }
public IList<QuestionModel> Template
{
get
{
return new List<QuestionModel>
{
new QuestionModel {/* defaults for new question */}
};
}
}
public QuestionListModel()
{
Questions = new List<QuestionModel>();
}
}
重要なのは、Templateプロパティを持っていることです。これも、IEnumerable<T>
必要な実際のモデルと同じタイプです。そうすれば、MVCによって自動番号付けが行われます。したがって、このモデルを使用すると、「Questions_0__Title」の番号が付けられたコレクションが取得され、「Template_0__Title」の名前が付けられた1つのテンプレート行も取得されます。
テンプレート行をUIから非表示にして、新しい行を追加するときに使用します。
かみそりでは、通常の質問をバインドするのと同じようにテンプレートをバインドします。唯一の違いは、非表示になっていること<div>
です。Count
また、質問リストのを非表示フィールドにバインドする必要もあります。私の場合、質問用のエディターテンプレートがあり、<div>
後で簡単にアクセスできるように、特定のセレクターを使用して内部にレンダリングします。したがって、最終的には次のようなものになります。
<div class="templateContainer">
<div class="question">
[Template]
</div>
</div>
<div class="items">
[for each of your items]
<div class="question">
[Question]
</div>
</div>
行を追加するときの秘訣は、javascriptを使用することです。
非表示フィールドからカウントを取得し、インクリメントします。
var counter = $("#QuestionsListCount");
var count = parseInt(counter.val());
count++;
テンプレートブロック全体を取得し、クローンを作成し(jqueryなどを使用.clone(true)
)、一意の名前を付け(たとえば、手順1のカウンター値を使用)、質問があるセクションに追加します。
var template = $("#templateContainer");
var newItem = template.clone(true);
var newId = "item_" + count;
var newQuestion = newItem.children().first();
newQuestion.attr("id", newId);
newQuestion.appendTo('#items');
新しく追加されたブロックへの入力(割り当てた新しいIDで見つけることができます)などの各項目について、ids => "Template_0"をステップ2の"Questions__count"に置き換え、names => "Template [ 0]」と「質問[ステップ2からのカウント]」。
$("#" + newId + " :input").each(function (index, input) {
input.id = input.id.replace("Template_0", "Questions_" + (count - 1));
input.name = input.name.replace("Template[0]", "Questions[" + (count - 1) + "]");
});
カウンターの非表示フィールドを更新します=>counter.val(count);
- ..。
- 利益!
さて、削除に関しては、私が行う方法は、それに対する私のViewModelには実際にIsDeleted
フラグがあり、それを質問エディターテンプレート内の非表示フィールドにもバインドします。そうすれば、削除は特定の質問を非表示にするのと同じくらい簡単で(質問セレクターが便利です)、そのIsDeleted
フィールドをtrueに設定します。リスト全体をデフォルトのモデルバインダーに戻すときは、削除されたものをすべて破棄する必要があります(または、バックエンドデータモデルによっては実際の削除を発行します)。
このようにして、削除されたアイテムを識別する個々の方法を処理したり、UI内のすべてのアイテムの番号を付け直したりする必要がなくなります。さらに、サーバー側のコードで、削除時に実際に何が発生するか(アクションの検証や取り消しなど)を決定できるという利点があります。
これは長い投稿ですが、実装はそれほど難しく(または長く)なく、一般的な方法で簡単に再利用できます。
乾杯!