7

ビューモデルの魔女に反復アイテムが含まれています。EditorFor() メソッドを使用してビューに配置します。

意見:

@model Models.MyModel 

@using (Html.BeginForm(@Model.Action, @Model.Controller))
{
    <div class="section" id="Terms">
        @Html.EditorFor(m => m.Terms)
    </div>

    <input type="submit" value="Save" />
}

モデル:

public class MyModel 
{
    public IEnumerable<Term> Terms  { get; set; }
}

EditorTemplates\Term.cshtml:

@model Models.Term

@if (Model != null) 
{
    <fieldset>
        <legend>Term</legend>

        @Html.HiddenFor(model => model.TermID)

        <div class="editor-label">
            @Html.LabelFor(model => model.Identifier)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Identifier)
            @Html.ValidationMessageFor(model => model.Identifier)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Description)
            @Html.ValidationMessageFor(model => model.Description)
        </div>

    </fieldset> 
}

ノックアウト.jsのこの例のように、ビューのリストから項目を動的に追加/削除できるようにしたいのですが、auto-idのMVC作成をどのように保持しますか??:

http://knockoutjs.com/examples/cartEditor.html

これに対する私の要件は次のとおりです。

  • 新しい用語を追加
  • 用語を削除
  • 追加された新しい用語ビューを検証する

SOに関する他の質問を読みましたが、これに関する真の決定的な答えは見つかりませんでした。ノックアウト.jsはこれを行うための受け入れられた方法ですか? Knockout AND MVC でこれを行う例はありますか?

ありがとう!

4

3 に答える 3

1

ノックアウトを使用せず、コードの再利用を最大化するソリューションを提供している Jarrett Meyer による MVC3 のネストされたコレクション モデルの投稿を見つけました。

これは add メソッドと delete メソッドの両方をカバーしています。add メソッドの概要を説明します。

モデル

public class Person {
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public IList<PhoneNumber> PhoneNumbers { get; set; }
  public IList<EmailAddress> EmailAddresses { get; set; }
  public IList<Address> Addresses { get; set; }
}

ビュー

//New.cshtml:    
@using (Html.BeginForm("New", "Person", FormMethod.Post))
{
  @Html.EditorForModel()
  <p>
    <button type="submit">
      Create Person
    </button>
  </p>
}

//Person.cshtml:
@Html.AntiForgeryToken()
@Html.HiddenFor(x => x.Id)

<p>
  <label>First Name</label>
  @Html.TextBoxFor(x => x.FirstName)
</p>
<p>
  <label>Last Name</label>
  @Html.TextBoxFor(x => x.LastName)
</p>
<div id="phoneNumbers">
  @Html.EditorFor(x => x.PhoneNumbers)
</div>
<p>
  @Html.LinkToAddNestedForm("Add Phone Number", "#phoneNumbers", ".phoneNumber", "PhoneNumbers", typeof(PhoneNumber))
</p>

//PhoneNumber.cshtml:
<div class="phoneNumber">
  <p>
    <label>Telephone Number</label>
    @Html.TextBoxFor(x => x.Number)
  </p>
  <br/>
</div>

ヘルパー

/// <param name="linkText">Text for Link</param>
/// <param name="containerElement">where this block will be inserted in the HTML using a jQuery append method</param>
/// <param name="counterElement">name of the class inserting, used for counting the number of items on the form</param>
/// <param name="collectionProperty">the prefix that needs to be added to the generated HTML elements</param>
/// <param name="nestedType">The type of the class you're inserting</param>
public static IHtmlString LinkToAddNestedForm<TModel>(this HtmlHelper<TModel> htmlHelper, string linkText,
    string containerElement, string counterElement, string collectionProperty, Type nestedType)
{
    var ticks = DateTime.UtcNow.Ticks;
    var nestedObject = Activator.CreateInstance(nestedType);
    var partial = htmlHelper.EditorFor(x => nestedObject).ToHtmlString().JsEncode();

    partial = partial.Replace("id=\\\"nestedObject", "id=\\\"" + collectionProperty + "_" + ticks + "_");
    partial = partial.Replace("name=\\\"nestedObject", "name=\\\"" + collectionProperty + "[" + ticks + "]");

    var js = string.Format("javascript:addNestedForm('{0}','{1}','{2}','{3}');return false;", containerElement,
        counterElement, ticks, partial);

    TagBuilder tb = new TagBuilder("a");
    tb.Attributes.Add("href", "#");
    tb.Attributes.Add("onclick", js);
    tb.InnerHtml = linkText;

    var tag = tb.ToString(TagRenderMode.Normal);
    return MvcHtmlString.Create(tag);
}

private static string JsEncode(this string s)
{
    if (string.IsNullOrEmpty(s)) return "";
    int i;
    int len = s.Length;

    StringBuilder sb = new StringBuilder(len + 4);
    string t;

    for (i = 0; i < len; i += 1)
    {
        char c = s[i];
        switch (c)
        {
            case '>':
            case '"':
            case '\\':
                sb.Append('\\');
                sb.Append(c);
                break;
            case '\b':
                sb.Append("\\b");
                break;
            case '\t':
                sb.Append("\\t");
                break;
            case '\n':
                //sb.Append("\\n");
                break;
            case '\f':
                sb.Append("\\f");
                break;
            case '\r':
                //sb.Append("\\r");
                break;
            default:
                if (c < ' ')
                {
                    //t = "000" + Integer.toHexString(c); 
                    string tmp = new string(c, 1);
                    t = "000" + int.Parse(tmp, System.Globalization.NumberStyles.HexNumber);
                    sb.Append("\\u" + t.Substring(t.Length - 4));
                }
                else
                {
                    sb.Append(c);
                }
                break;
        }
    }
    return sb.ToString();
}

Javascript

//since the html helper can change the text of the item inserted but not the index,
//this replaces the 'ticks' with the correct naming for the collection of properties
function addNestedForm(container, counter, ticks, content) {
  var nextIndex = $(counter).length;
  var pattern = new RegExp(ticks, "gi");

  content = content.replace(pattern, nextIndex);
  $(container).append(content);
} 
于 2014-05-06T13:17:12.797 に答える
0

次のことを行う必要があります。

  1. モデルをコントローラーに送信し、ターム用に 1 つの編集可能なフィールドをレンダリングします。
  2. ユーザーにこれを送信するように依頼するか、[追加] をクリックして用語を追加します。
  3. ユーザーが追加をクリックすると、既存のフィールドのコピーを作成し、それらを空にするか、新しいフィールドを作成できるようにします。
  4. ユーザーが送信すると、一連の用語を受け入れるアクションに送り返され、データベースに追加されます。または、上記の例のような ajax を使用するか、この例から、サーバーに送信されるものが json 配列オブジェクトであり、名前付き要素で形成されていないことがわかります。
  5. 作成時に処理することも、送信時に処理することもできます。

アプリケーションにも依存するため、ノックアウトは、古いコピーから新しいものを作成するステップ 3 でクライアントを支援するだけです。そのためのJQueryテンプレートとjson2を訴えて、古いブラウザーサポートでシリアル化することもできます。

理解する必要があるのは、クライアントにアクセスしたら、モデルをここに一度送信したことなので、サーバー側について心配する必要はありません。クライアント側で構築するものはすべて、一度に 1 つのモデルを saveTerm アクションに送信して、用語 ID やその他の情報を使用して json を再実行するか、saveTerm のコレクションを json 配列として返すことができ、正常に動作します。

ajaxではなくpostBackで配列を送信することを考えている場合は、フォーム要素名を同じにして、用語入力フィールドを複製して送信してください。MVC は、json の場合と同様に、それらを用語の配列にマップします。

于 2013-02-05T16:31:16.373 に答える
0

ノックアウト MVC が必要http://knockoutmvc.com/CartEditor

これにはノックアウトを使用する必要はありません。本当に必要なのは、バリデーションを備えた JavaScript と、MVC 側の安らかなコントローラー アクションにマップするアクションの作成/削除です。それをどのように実装するかはあなた次第です。ノックアウトはそれを簡単にします。

于 2013-02-05T04:51:39.910 に答える