Como usar o knockout.js com o ASP.NET MVC ViewModels?

129

Recompensa

Já faz um tempo e ainda tenho algumas perguntas pendentes. Espero que, adicionando uma recompensa, talvez essas perguntas sejam respondidas.

  1. Como você usa ajudantes de html com knockout.js
  2. Por que o documento estava pronto para fazê-lo funcionar (consulte a primeira edição para obter mais informações)

  3. Como faço algo assim se estou usando o mapeamento de nocaute com meus modelos de exibição? Como não tenho uma função devido ao mapeamento.

    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
    
    };
  4. Eu quero usar plug-ins, por exemplo, eu quero poder reverter observáveis ​​como se um usuário cancelasse uma solicitação, eu quero poder voltar ao último valor. Da minha pesquisa, isso parece ser alcançado por pessoas que criam plugins como editáveis

    Como uso algo assim se estou usando mapeamento? Eu realmente não quero ir para um método em que eu tenho no meu mapeamento manual de visão, onde mapeei cada campo MVC viewMode para um campo de modelo KO, pois eu quero o mínimo de javascript embutido possível e isso parece o dobro do trabalho, e isso por que eu gosto desse mapeamento.

  5. Preocupa-me que, para facilitar esse trabalho (usando o mapeamento), eu perca muito poder de KO, mas, por outro lado, preocupo-me com o fato de que o mapeamento manual seja apenas muito trabalhoso e faça com que minhas visualizações contenham informações e informações demais. pode se tornar no futuro mais difícil de manter (por exemplo, se eu remover uma propriedade no modelo MVC, também tenho que movê-la no viewmodel KO)


Correio Original

Estou usando o asp.net mvc 3 e estou olhando para o nocaute, pois parece muito legal, mas estou tendo dificuldade para descobrir como ele funciona com o asp.net mvc, especialmente para ver os modelos.

Para mim agora eu faço algo parecido com isto

 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; }

}

Eu teria um Vm que possui algumas propriedades básicas como CourseName e terá alguma validação simples em cima dele. O modelo Vm pode conter outros modelos de visualização, se necessário.

Eu passaria esse VM para a View onde usaria ajudantes html para me ajudar a exibi-lo ao usuário.

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

Talvez eu tenha alguns loops de foreach ou algo para extrair os dados da coleção de modelos de exibição do aluno.

Então, quando eu serialize arrayenviava o formulário, usava o jquery e o enviava para um método de ação do controlador que o vinculava novamente ao viewmodel.

Com o knockout.js, tudo é diferente, pois agora você tem modelos de exibição para ele e, de todos os exemplos que vi, eles não usam auxiliares de html.

Como você usa esses 2 recursos do MVC com o knockout.js?

Encontrei este vídeo e, brevemente (nos últimos minutos do vídeo às 18:48), é uma maneira de usar os modelos de visualização, basicamente, com um script embutido que possui o knockmod.js viewmodel que recebe os valores no ViewModel.

Essa é a única maneira de fazer isso? Que tal no meu exemplo ter uma coleção de modelos de exibição? Preciso ter um loop foreach ou algo para extrair todos os valores e atribuí-lo ao nocaute?

Quanto aos auxiliares de html, o vídeo não diz nada sobre eles.

Essas são as duas áreas que me confundem, já que poucas pessoas parecem falar sobre isso e me deixa confuso sobre como os valores iniciais e tudo estão chegando ao ponto de vista quando qualquer exemplo é apenas um exemplo de valor codificado.


Editar

Estou tentando o que Darin Dimitrov sugeriu e isso parece funcionar (eu tive que fazer algumas alterações no código dele). Não sei por que tive que usar o documento pronto, mas de alguma forma nem tudo estava pronto sem ele.

@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>

Eu tive que envolvê-lo em torno de um documento jquery pronto para fazê-lo funcionar.

Eu também recebo este aviso. Não tenho certeza do que se trata.

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

Então, eu tenho um ponto de partida, acho que pelo menos será atualizado quando eu fizer mais algumas brincadeiras e como isso funciona.

Estou tentando passar pelos tutoriais interativos, mas use o um ViewModel.

Ainda não sei como lidar com essas peças

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

ou

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
    };


Editar 2

Consegui descobrir o primeiro problema. Nenhuma pista sobre o segundo problema. Ainda assim. Alguém tem alguma idéia?

 @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>

Controlador

  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);
    }
chobo2
fonte
2
Acabei de escrever um post para responder a outra pergunta semelhante: roysvork.wordpress.com/2012/12/09/… Pode não responder completamente à sua pergunta, mas fornece uma boa idéia de como as coisas poderiam funcionar. Espero acompanhar isso com mais um post em um futuro não muito distante. Sinta-se à vontade para fazer qualquer pergunta nos comentários do post ou aqui, se precisar de mais informações.
além do código

Respostas:

180

Eu acho que resumi todas as suas perguntas, se eu perdi alguma coisa, por favor me avise ( Se você pudesse resumir todas as suas perguntas em um só lugar, seria legal =))

Nota. Compatibilidade com o ko.editableplug-in adicionado

Faça o download do código completo

Como você usa ajudantes de html com knockout.js

Isso é facil:

@Html.TextBoxFor(model => model.CourseId, new { data_bind = "value: CourseId" })

Onde:

  • value: CourseIdindica que você está vinculando a valuepropriedade do inputcontrole à CourseIdpropriedade do seu modelo e do seu modelo de script

O resultado é:

<input data-bind="value: CourseId" data-val="true" data-val-number="The field CourseId must be a number." data-val-required="The CourseId field is required." id="CourseId" name="CourseId" type="text" value="12" />

Por que o documento estava pronto para fazê-lo funcionar (consulte a primeira edição para obter mais informações)

Ainda não entendo por que você precisa usar o readyevento para serializar o modelo, mas parece que ele é simplesmente necessário (para não se preocupar com isso)

Como faço algo assim se estou usando o mapeamento de nocaute com meus modelos de exibição? Como não tenho uma função devido ao mapeamento.

Se bem entendi, você precisa anexar um novo método ao modelo KO, bem, é fácil mesclar modelos

Para obter mais informações, na seção Mapeamento de diferentes fontes,

function viewModel() {
    this.addStudent = function () {
        alert("de");
    };
};

$(function () {
    var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
    var mvcModel = ko.mapping.fromJSON(jsonModel);

    var myViewModel = new viewModel();
    var g = ko.mapping.fromJS(myViewModel, mvcModel);

    ko.applyBindings(g);
});

Sobre o aviso que você estava recebendo

Aviso 1 A compilação condicional está desativada -> @ Html.Raw

Você precisa usar aspas

Compatibilidade com o plug-in ko.editable

Eu pensei que seria mais complexo, mas acontece que a integração é realmente fácil, para tornar seu modelo editável basta adicionar a seguinte linha: (lembre-se de que, neste caso, estou usando um modelo misto, de servidor e adicionar extensão no cliente e o editável simplesmente funciona ... é ótimo):

    ko.editable(g);
    ko.applyBindings(g);

A partir daqui, você só precisa brincar com suas ligações usando as extensões adicionadas pelo plug-in, por exemplo, tenho um botão para começar a editar meus campos como este e neste botão inicio o processo de edição:

    this.editMode = function () {
        this.isInEditMode(!this.isInEditMode());
        this.beginEdit();
    };

Então eu tenho confirmar e cancelar botões com o seguinte código:

    this.executeCommit = function () {
        this.commit();
        this.isInEditMode(false);
    };
    this.executeRollback = function () {
        if (this.hasChanges()) {
            if (confirm("Are you sure you want to discard the changes?")) {
                this.rollback();
                this.isInEditMode(false);
            }
        }
        else {
            this.rollback();
            this.isInEditMode(false);
        }
    };

E, finalmente, eu tenho um campo para indicar se os campos estão no modo de edição ou não, isso é apenas para vincular a propriedade enable.

this.isInEditMode = ko.observable(false);

Sobre sua pergunta sobre matriz

Talvez eu tenha alguns loops de foreach ou algo para extrair os dados da coleção de modelos de exibição do aluno.

Então, quando eu enviava o formulário, usava jquery e serializava a matriz e a enviava para um método de ação do controlador que a vinculava novamente ao viewmodel.

Você pode fazer o mesmo com o KO, no exemplo a seguir, criarei a seguinte saída:

insira a descrição da imagem aqui

Basicamente aqui, você tem duas listas, criadas usando Helperse vinculadas ao KO; elas têm um dblClickevento vinculado que, quando acionado, remove o item selecionado da lista atual e o adiciona à outra lista, quando você publica noController no conteúdo de cada lista é enviada como dados JSON e reconectada ao modelo do servidor

Pepitas:

Scripts externos .

Código do controlador

    [HttpGet]
    public ActionResult Index()
    {
        var m = new CourseVM { CourseId = 12, CourseName = ".Net" };

        m.StudentViewModels.Add(new StudentVm { ID = 545, Name = "Name from server", Lastname = "last name from server" });

        return View(m);
    }

    [HttpPost]
    public ActionResult Index(CourseVM model)
    {
        if (!string.IsNullOrWhiteSpace(model.StudentsSerialized))
        {
            model.StudentViewModels = JsonConvert.DeserializeObject<List<StudentVm>>(model.StudentsSerialized);
            model.StudentsSerialized = string.Empty;
        }

        if (!string.IsNullOrWhiteSpace(model.SelectedStudentsSerialized))
        {
            model.SelectedStudents = JsonConvert.DeserializeObject<List<StudentVm>>(model.SelectedStudentsSerialized);
            model.SelectedStudentsSerialized = string.Empty;
        }

        return View(model);
    }

Modelo

public class CourseVM
{
    public CourseVM()
    {
        this.StudentViewModels = new List<StudentVm>();
        this.SelectedStudents = new List<StudentVm>();
    }

    public int CourseId { get; set; }

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

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

    public string StudentsSerialized { get; set; }
    public string SelectedStudentsSerialized { get; set; }
}

public class StudentVm
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Lastname { get; set; }
}

Página CSHTML

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>CourseVM</legend>

        <div>
            <div class="editor-label">
                @Html.LabelFor(model => model.CourseId)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseId, new { data_bind = "enable: isInEditMode, value: CourseId" })
                @Html.ValidationMessageFor(model => model.CourseId)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.CourseName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseName, new { data_bind = "enable: isInEditMode, value: CourseName" })
                @Html.ValidationMessageFor(model => model.CourseName)
            </div>
            <div class="editor-label">
                @Html.LabelFor(model => model.StudentViewModels);
            </div>
            <div class="editor-field">

                @Html.ListBoxFor(
                    model => model.StudentViewModels,
                    new SelectList(this.Model.StudentViewModels, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: StudentViewModels, optionsText: 'Name', value: leftStudentSelected, event: { dblclick: moveFromLeftToRight }"
                    }
                )
                @Html.ListBoxFor(
                    model => model.SelectedStudents,
                    new SelectList(this.Model.SelectedStudents, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: SelectedStudents, optionsText: 'Name', value: rightStudentSelected, event: { dblclick: moveFromRightToLeft }"
                    }
                )
            </div>

            @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
            @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })
            @Html.HiddenFor(model => model.StudentsSerialized, new { data_bind = "value: StudentsSerialized" })
            @Html.HiddenFor(model => model.SelectedStudentsSerialized, new { data_bind = "value: SelectedStudentsSerialized" })
        </div>

        <p>
            <input type="submit" value="Save" data-bind="enable: !isInEditMode()" /> 
            <button data-bind="enable: !isInEditMode(), click: editMode">Edit mode</button><br />
            <div>
                <button data-bind="enable: isInEditMode, click: addStudent">Add Student</button>
                <button data-bind="enable: hasChanges, click: executeCommit">Commit</button>
                <button data-bind="enable: isInEditMode, click: executeRollback">Cancel</button>
            </div>
        </p>
    </fieldset>
}

Scripts

<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-2.1.0.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout.mapping-latest.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ko.editables.js")" type="text/javascript"></script>

<script type="text/javascript">
    var g = null;
    function ViewModel() {
        this.addStudent = function () {
            this.StudentViewModels.push(new Student(25, "my name" + new Date(), "my last name"));
            this.serializeLists();
        };
        this.serializeLists = function () {
            this.StudentsSerialized(ko.toJSON(this.StudentViewModels));
            this.SelectedStudentsSerialized(ko.toJSON(this.SelectedStudents));
        };
        this.leftStudentSelected = ko.observable();
        this.rightStudentSelected = ko.observable();
        this.moveFromLeftToRight = function () {
            this.SelectedStudents.push(this.leftStudentSelected());
            this.StudentViewModels.remove(this.leftStudentSelected());
            this.serializeLists();
        };
        this.moveFromRightToLeft = function () {
            this.StudentViewModels.push(this.rightStudentSelected());
            this.SelectedStudents.remove(this.rightStudentSelected());
            this.serializeLists();
        };
        this.isInEditMode = ko.observable(false);
        this.executeCommit = function () {
            this.commit();
            this.isInEditMode(false);
        };
        this.executeRollback = function () {
            if (this.hasChanges()) {
                if (confirm("Are you sure you want to discard the changes?")) {
                    this.rollback();
                    this.isInEditMode(false);
                }
            }
            else {
                this.rollback();
                this.isInEditMode(false);
            }
        };
        this.editMode = function () {
            this.isInEditMode(!this.isInEditMode());
            this.beginEdit();
        };
    }

    function Student(id, name, lastName) {
        this.ID = id;
        this.Name = name;
        this.LastName = lastName;
    }

    $(function () {
        var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
        var mvcModel = ko.mapping.fromJSON(jsonModel);

        var myViewModel = new ViewModel();
        g = ko.mapping.fromJS(myViewModel, mvcModel);

        g.StudentsSerialized(ko.toJSON(g.StudentViewModels));
        g.SelectedStudentsSerialized(ko.toJSON(g.SelectedStudents));

        ko.editable(g);
        ko.applyBindings(g);
    });
</script>

Nota: Acabei de adicionar estas linhas:

        @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
        @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })

Como quando eu envio o formulário, meus campos são desabilitados e, portanto, os valores não foram transmitidos ao servidor, por isso adicionei alguns campos ocultos para fazer o truque

Jupaol
fonte
Hmm muito informativo. Pela sua resposta e pela resposta de Pual, acho que quase recebi todas as minhas perguntas, exceto como usar plug-ins como editáveis. Espero que alguém saiba como eu posso usar isso.
chobo2
1
Acabei de adicionar compatibilidade com o ko.editablesplug-in, você pode verificar a resposta atualizada ou se você quiser, você pode baixar todo o projeto para executá-lo localmente
Jupaol
Vou dar uma olhada quando puder. Muita coisa precisava mudar para que funcionasse? Eu estou querendo saber se, para cada plug-in, acho que precisarei fazer alterações e, em seguida, manter minha própria versão.
chobo2
Não. Você ficará surpreso, é quase
pronto para o uso
1
Graças a um grupo, aprendi várias novas estratégias com a sua resposta. Parabéns!
sky-dev
23

Você pode serializar seu modelo de exibição do ASP.NET MVC em uma variável javascript:

@model CourseVM
<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));
    // go ahead and use the model javascript variable to bind with ko
</script>

Existem muitos exemplos na documentação do knockout que você pode analisar.

Darin Dimitrov
fonte
1
Sim, eu passei pelo tutorial interativo que eles têm no site, mas realmente nunca vejo nada a ver com o asp.net mvc. Vejo que eles também têm algum plugin de mapeamento, mas não sabem como isso se encaixa. No seu exemplo, como você o vincularia ao modelo de knockout (em outro script). Eu realmente quero ter tão pouco javascript em linha como possível (não é preferível, mas eu acho que não é possível)
chobo2
2
Que problema você está tentando resolver? Se você deseja visualizações do MVC e está satisfeito com a maneira de usá-las, pode ficar lá. Se você deseja ligação e manipulação de dados do lado do cliente, o KO é uma ótima opção. Você pode gerar seu modelo de exibição KO a partir do seu código MVC, como mostra esta resposta. Ele pega a vm e a serializa para json. Em seguida, no cliente, você pode mapear os resultados para um modelo de exibição em javascript. Em seguida, vincule o viewmodel à view e tudo estará pronto. A chave é que o MVC e o KO não precisam ser acoplados de maneira alguma, a menos que você queira que eles sejam. Tudo depende do problema que você está tentando resolver.
John Papa
1
É normal que você não esteja vendo nada com o asp.net mvc. Knockout é uma estrutura do lado do cliente. Ele não sabe nem se importa com o idioma do servidor que você está usando. Essas duas estruturas devem ser absolutamente dissociadas.
precisa
@ JohnPapa - Eu gosto do jeito que faço agora, mas também gosto de aprender coisas novas (vejo que o KO pode ser muito útil em algumas situações). Eu sei que KO é um script do lado do cliente, mas para mim eu os vejo trabalhando juntos. Atualmente, gero minhas visualizações usando modelos de visualização e auxiliares de html. Então, na minha opinião, o KO precisa trabalhar junto com isso. Por exemplo, digamos que você tenha a caixa de diálogo de edição. Como você projetaria e preencheria os valores de um banco de dados nesses campos. Se eu estivesse usando do meu jeito, seria uma visualização dos auxiliares html que possui um viewModel. Preencheria o viewmodel e o enviaria através do Action Method e o utilizaria.
chobo2
1
@ chobo2, knockout é uma estrutura do lado do cliente. Ele usa modelos de visualização no cliente para implementar o padrão MVC no cliente. O servidor está desacoplado. Você também pode usar os modelos de exibição. São apenas 2 lugares diferentes. Se você tem alguma lógica complexa que deseja implementar no cliente usando javascript, o nocaute pode simplificar isso. Caso contrário, honestamente, você não precisa disso.
precisa
2

Para obter as propriedades computadas adicionais após o mapeamento do servidor, você precisará aprimorar ainda mais seus modelos de exibição no lado do cliente.

Por exemplo:

var viewModel = ko.mapping.fromJS(model);

viewModel.capitalizedName = ko.computed(function() {...}, viewModel);

Portanto, toda vez que você mapeia a partir do JSON bruto, é necessário reaplicar as propriedades calculadas.

Além disso, o plug-in de mapeamento oferece a capacidade de atualizar incrementalmente um modelo de exibição, em vez de recriá-lo toda vez que você vai e volta (use um parâmetro adicional em fromJS):

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);

E isso executa uma atualização incremental de dados em seu modelo, apenas de propriedades mapeadas. Você pode ler mais sobre isso na documentação de mapeamento

Você mencionou nos comentários sobre a resposta de Darin ao pacote FluentJSON . Sou o autor disso, mas seu caso de uso é mais específico que o ko.mapping. Geralmente, eu o usaria apenas se os seus modelos de exibição fossem de sentido único (ou seja, servidor -> cliente) e, em seguida, os dados fossem postados novamente em algum formato diferente (ou nenhum). Ou se o seu modelo de exibição em javascript precisar estar em um formato substancialmente diferente do modelo do seu servidor.

Paul Tyng
fonte
Hummm, acho que talvez o FluentJSON não seja para mim, pois meus viewmodels na maioria das vezes seguem os dois lados (eu normalmente o envio através do json e depois o vinculo ao viewmodel no parâmetro do método de ação). Você sabe como eu poderia usar os plugins que mencionei como editáveis? Finalmente, estou perdendo algum tipo de funcionalidade usando o mapeamento e tentando usar o meu viewmodel vs não usá-lo?
precisa saber é o seguinte
Eu não usei nenhum dos plugins, então não tenho certeza. O que eu fiz no passado foi apenas para assinar todas as alterações e manter uma pilha de estados de viewmodel serializados que eu pressionaria para alterar e aparecia para desfazer ( consulte esta pergunta ).
Paul Tyng
o mapeamento não o impede de nenhuma funcionalidade, você só precisa ter certeza e observar suas convenções sobre como ele lida com o mapeamento de e para JS para fazer com que tudo funcione perfeitamente bem.
Paul Tyng
Bem, a resposta aceita para a pergunta que você postou é basicamente qual seria o plugin. Isso é o que está me confundindo, como você pode ver, eles criam um viewmodel e, em seguida, usam a função que criaram (ko.observableArrayWithUndo ([])). Se estou fazendo mapeamento, não sei como fazer isso. A única coisa que vem à mente é escrever meu próprio mapeamento (o que eu duvido que eu poderia corrigir no momento) que desfaz o observável ou mapeia cada propriedade, mas basicamente tenho modelos de exibição duplicados, um para o servidor e outro para o cliente. medo de que se torne
impossível de manter
Ah, sim, desculpe, eu estava falando sobre a minha resposta a essa pergunta, desculpe, deveria ter ligado diretamente.
Paul Tyng