Jak używać knockout.js z ASP.NET MVC ViewModels?

Hojność

Minęło trochę czasu i wciąż mam kilka znakomitych pytań. Mam nadzieję, że dodanie bounty może dać odpowiedź na te pytania.

Jak używać pomocników HTML z knockout.js

Dlaczego dokument był gotowy do jego uruchomienia (więcej informacji można znaleźć w pierwszej edycji)

Jak zrobić coś takiego, jeśli korzystam z mapowania nokautów w moich modelach widoku? Ponieważ nie mam funkcji z powodu mapowania.

function AppViewModel() {

    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {

    var currentVal = this.lastName();        // Read the current value

    this.lastName(currentVal.toUpperCase()); // Write back a modified value

};

Chcę używać wtyczek, na przykład Chcę móc wycofać obserwowalne dane, tak jakby użytkownik anulował żądanie Chcę móc wrócić do ostatniej wartości. Z moich badań wynika, że ​​ludzie robią takie wtyczkiedytowalne

Jak mogę użyć czegoś takiego, jeśli używam mapowania? Naprawdę nie chcę przechodzić do metody, w której w moim widoku mapowanie ręczne było mapowaniem każdego pola MVC viewMode na pole modelu KO, ponieważ chciałbym mieć jak najmniejszy wbudowany JavaScript, a to po prostu wygląda na podwójną pracę i to jest dlaczego lubię to mapowanie.

Obawiam się, że ułatwienie tej pracy (za pomocą mapowania) stracę dużo mocy KO, ale z drugiej strony obawiam się, że ręczne mapowanie będzie po prostu dużo pracy i sprawi, że moje poglądy będą zawierały zbyt wiele informacji i może stać się w przyszłości trudniejszy w utrzymaniu (powiedzmy, że jeśli usunę właściwość w modelu MVC, to muszę go przenieść również w viewmodelu KO)

Oryginalny post

Korzystam z asp.net mvc 3 i szukam nokautu, ponieważ wygląda to całkiem fajnie, ale mam problem ze zrozumieniem, jak to działa z mvc asp.net, zwłaszcza modele widoku.

Dla mnie teraz robię coś takiego

 public class CourseVM
    {
        public int CourseId { get; set; }
        [Required(ErrorMessage = "Course name is required")]
        [StringLength(40, ErrorMessage = "Course name cannot be this long.")]
        public string CourseName{ get; set; }


        public List<StudentVm> StudentViewModels { get; set; }

}

Miałbym Vm, który ma kilka podstawowych właściwości, takich jak CourseName i będzie miał prostą walidację. Model Vm może zawierać również inne modele widoku, jeśli to konieczne.

Następnie przekazałbym Vm do widoku, gdybym użył pomocników HTML, aby pomóc mi wyświetlić go użytkownikowi.

@Html.TextBoxFor(x => x.CourseName)

Mógłbym mieć jakieś pętle foreach lub coś, aby uzyskać dane z kolekcji modeli widoku studenta.

Następnie, gdy wysyłałem formularz, używałbym jquery iserialize array i wyślij go do metody działania kontrolera, która zwiąże go z powrotem do modelu widoku.

Z knockout.js wszystko jest inne, ponieważ masz teraz viewmodele i ze wszystkich przykładów widziałem, że nie używają pomocników HTML.

Jak korzystać z tych dwóch funkcji MVC za pomocą knockout.js?

znalazłemten film i to w skrócie (ostatnie kilka minut filmu 18:48) idzie w kierunku użycia viewmodeli poprzez posiadanie wbudowanego skryptu, który ma viewmodel knockout.js, który otrzymuje przypisane wartości w ViewModel.

Czy to jedyny sposób, aby to zrobić? Co powiesz na mój przykład z kolekcją viewmodeli? Czy muszę mieć pętlę foreach lub coś, aby wyodrębnić wszystkie wartości i przypisać je do nokautu?

Jeśli chodzi o pomocników HTML, wideo nic o nich nie mówi.

Są to dwa obszary, które dezorientują mnie, ponieważ niewielu ludzi mówi o tym i pozostawia mnie zdezorientowanym, jak początkowe wartości i wszystko dociera do widoku, gdy przykład jest tylko pewnym zakodowanym przykładem.

Edytować

Próbuję tego, co zasugerował Darin Dimitrov i wydaje się, że to działa (musiałem jednak wprowadzić pewne zmiany do jego kodu). Nie wiem, dlaczego musiałem użyć gotowego dokumentu, ale bez niego wszystko nie było gotowe.

@model MvcApplication1.Models.Test

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
   <script type="text/javascript">

   $(function()
   {
      var model = @Html.Raw(Json.Encode(Model));


// Activates knockout.js
ko.applyBindings(model);
   });

</script>

</head>
<body>
    <div>
        <p>First name: <strong data-bind="text: FirstName"></strong></p>
        <p>Last name: <strong data-bind="text: LastName"></strong></p>
        @Model.FirstName , @Model.LastName
    </div>
</body>
</html>

Musiałem zawinąć go w dokument jquery gotowy do działania.

Dostaję także to ostrzeżenie. Nie jestem pewien, o co w tym wszystkim chodzi.

Warning 1   Conditional compilation is turned off   -> @Html.Raw

Mam więc punkt wyjścia, o którym myślę, że przynajmniej się zaktualizuje, kiedy będę się trochę bawił i jak to działa.

Próbuję przejść przez interaktywne samouczki, ale zamiast tego korzystam z ViewModel.

Nie wiem jeszcze, jak poradzić sobie z tymi częściami

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
}

lub

function AppViewModel() {
    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    };

Edytuj 2

Udało mi się ustalić pierwszy problem. Nie ma pojęcia o drugim problemie. A jednak. Czy ktoś ma jakieś pomysły?

 @model MvcApplication1.Models.Test

    @{
        Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
        <title>Index</title>
        <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
       <script type="text/javascript">

       $(function()
       {
        var model = @Html.Raw(Json.Encode(Model));
        var viewModel = ko.mapping.fromJS(model);
        ko.applyBindings(viewModel);

       });

    </script>

    </head>
    <body>
        <div>
            @*grab values from the view model directly*@
            <p>First name: <strong data-bind="text: FirstName"></strong></p>
            <p>Last name: <strong data-bind="text: LastName"></strong></p>

            @*grab values from my second view model that I made*@
            <p>SomeOtherValue <strong data-bind="text: Test2.SomeOtherValue"></strong></p>
            <p>Another <strong data-bind="text: Test2.Another"></strong></p>

            @*allow changes to all the values that should be then sync the above values.*@
            <p>First name: <input data-bind="value: FirstName" /></p>
            <p>Last name: <input data-bind="value: LastName" /></p>
            <p>SomeOtherValue <input data-bind="value: Test2.SomeOtherValue" /></p>
            <p>Another <input data-bind="value: Test2.Another" /></p>

           @* seeing if I can do it with p tags and see if they all update.*@
            <p data-bind="foreach: Test3">
                <strong data-bind="text: Test3Value"></strong> 
            </p>

     @*took my 3rd view model that is in a collection and output all values as a textbox*@       
    <table>
        <thead><tr>
            <th>Test3</th>
        </tr></thead>
          <tbody data-bind="foreach: Test3">
            <tr>
                <td>    
                    <strong data-bind="text: Test3Value"></strong> 
<input type="text" data-bind="value: Test3Value"/>
                </td>
            </tr>    
        </tbody>
    </table>

Kontroler

  public ActionResult Index()
    {
              Test2 test2 = new Test2
        {
            Another = "test",
            SomeOtherValue = "test2"
        };

        Test vm = new Test
        {
            FirstName = "Bob",
            LastName = "N/A",
             Test2 = test2,

        };
        for (int i = 0; i < 10; i++)
        {
            Test3 test3 = new Test3
            {
                Test3Value = i.ToString()
            };

             vm.Test3.Add(test3);
        }

        return View(vm);
    }

questionAnswers(3)

yourAnswerToTheQuestion