2017-09-08 1 views
0

Say J'utilise unValeur d'affichage à knock-out à partir Html Aide

@Html.TetboxFor(m => m.FirstName, new { data_bind= "value:first_name" }) 

que je suis peuplant de mon MVC viewmodel et je veux transmettre cette valeur à mes knockoutJs voir le modèle. J'ai vu la suggestion de créer un objet javascript à partir de mon viewmodel. Je suis en mesure d'obtenir avec succès la valeur en disant la viewmodel que

self.first_name = ko.observable($("#FirstName").val()) 

J'ai essayé d'utiliser la liaison « texte » qui rend mes données à partir du viewmodel mvc mais ne renvoie pas les données dans le modèle de vue knock-out et la La liaison 'value' efface mon helper HTML mais renvoie les données au modèle de vue défonçable. J'ai également essayé d'utiliser la liaison 'textinput'. Y at-il un meilleur moyen que ce que j'utilise ou est le principal moyen de le faire pour remplir le modèle de vue knock-out directement à partir du serveur? Merci

+0

Vous ne même pas besoin d'ASP.NET Razor juste utiliser knockout:

+0

ASP.NET MVC et Razor ne sont pas un excellent moyen de construire des applications web, –

+0

Je suis d'accord avec vous .... mais j'aime utiliser l'aide Html pour peupler des choses parfois. –

Répondre

2

Je sais que je vais être noté pour vous avoir donné une autre réponse, mais c'est correct car cela vaut la peine de partager une façon différente de résoudre votre problème, c'est plus simple et plus puissant. Si cela ne vous dérange pas une suggestion, éloignez-vous de ASP.NET MVC Razor templating, il n'est pas puissant, il est étroitement couplant votre backend à votre front d'une manière pas très différente de celle faite par ASP.NET Web Forms . Ici, à titre d'exemple de la puissance de KnockoutJs avec ASP.NET MVC, mais pas de Razor pour lier les données du modèle aux éléments View, knockoutjs est entièrement utilisé à la place. Une clé à emporter est que le modèle C# est construit dynamiquement dans KnockoutJs, en utilisant knockout.mapping.js. Ainsi, lorsque vous ajoutez une nouvelle propriété à votre modèle C#, elle est automatiquement disponible dans votre Knockout ViewModel.

Voici un extrait d'un .cshtml View en utilisant aucune syntaxe Razor pour le modèle forme/entrée de liaison:

@using System.Activities.Statements 
@using System.Web.Optimization 
@model Mvc.Models.ProjectModel 

@{ 
    ViewBag.Title = "Start New Project"; 
    Layout = "~/Views/Shared/_BuildLayout.cshtml"; 
} 


@section sideMenuCustomContent{ 
    @Html.Partial("_PartialSidebarPricing") 
} 

@using (Html.BeginForm("StartSubmit", "Start", null, FormMethod.Post, new { @role = "form", id = "formStart", enctype = "multipart/form-data" })) 
{ 
    <input type="hidden" value="@Url.RouteUrl("UploadStep")" data-bind="valueWithInit: 'UrlWithIdUploadStep'" /> 
    <input type="hidden" value="@Url.Action("GetProjectModel", "Start")" data-bind="valueWithInit: 'UrlRootGetProjectModel'" /> 
    <input type="hidden" value="@Url.Action("StyleInfo", "Start")" data-bind="valueWithInit: 'UrlRootStyleInfo'" /> 
    <input type="hidden" value="@Url.Action("GetCoverColorSwatchUrl", "Asset")" data-bind="valueWithInit: 'UrlRootGetCoverColorImage'" /> 


    <div class="row"> 
     <div class="col-lg-6 col-md-6 featuredTextContainer"> 
      <div class="style-hero" > 
       <h1 class="style-title" data-bind="text: Style.StyleName"></h1> 
       <div class="style-start-price" >Starting at: <span data-bind="text: Application.FormatCurrency(BookBasePrice())"></span></div> 
       <div class="style-caption" > 
        <p data-bind="text: Style.DisplayText" ></p> 
       </div> 
      </div> 
     </div> 

     <div id="book-options-right-column" class="col-lg-4 col-md-6 build-right-column well-black"> 
      <div class="form-group"> 
       <input id="tbxPrjName" type="text" placeholder="Project Name" data-bind="value: Name" class="couture-input-underline couture-text-white placeholder-center text-center" /> 
      </div> 
      <div class="form-group"> 
       <input style="width: 80%;" type="text" class="couture-input-underline couture-text-white placeholder-center text-center" placeholder="Estimated Page Count" data-bind="value: PageCountEstimated, valueUpdate: 'afterkeydown'" /> 
       <a data-toggle="popover" 
        class="popover-250w" 
        data-placement="bottom" 
        data-content="Estimate just to help you with pricing, exact page count will be tracked for you. Click the Hamburger Menu in left corner to see current pricing." 
        data-title="Estimated Page Count"> 
        <i class="glyphicon glyphicon-question-sign"></i> 
       </a> 
      </div> 


         <input type="button" id="stampYes" data-bind="click: OnTextStampingYes, css: { 'selected': TextStamping }" class="btn-couture btn-couture-transparent btn-round" value="Y" /> 
         <input type="button" id="stampNo" data-bind="click: OnTextStampingNo, css: { 'selected': !TextStamping() }" class="btn-couture btn-couture-transparent btn-round" value="N"> 
        </div> 
        <div class="form-group" data-bind="visible: Style.HasBackCoverOption"> 
         <label>Back Cover Image</label> 
         <a data-toggle="popover" 
          class="popover-250w" 
          data-placement="bottom" 
          data-content="You’ll be able to upload your back cover image on the next page." 
          data-title="Back Cover Image"> 
          <i class="glyphicon glyphicon-question-sign"></i> 
         </a> 
         <br /> 
         <span> 
          <input type="button" id="BackCoverYes" data-bind="click: onBackCoverChange, css: { 'selected': CoverImageBack }" class="btn-couture btn-couture-transparent btn-round" value="Y" /> 
          <input type="button" id="BackCoverNo" data-bind="click: onBackCoverChangeNo, css: { 'selected': !CoverImageBack() }" class="btn-couture btn-couture-transparent btn-round" value="N" /> 
         </span> 
        </div> 
       </div> 
      </div> 
      <div class="form-group"> 
       <div data-bind="visible: !PricingPartialShowFinalTotals()"> 
        <button type="button" class="btn-couture btn-couture-transparent btn-couture-white btn-couture-large" data-bind="text: PricingPartialSubmitBtnText, disable: PricingPartialSubmitLock, click: formSubmit"></button> 
       </div> 
      </div> 
     </div> 
    </div> 



    <div class="form-group"> 
      <div data-bind="visible: !PricingPartialShowFinalTotals()"> 
       <button type="button" class="btn-couture btn-couture-transparent btn-couture-white btn-couture-large" data-bind="text: PricingPartialSubmitBtnText, disable: PricingPartialSubmitLock, click: formSubmit"></button> 
      </div> 
     </div> 

}@*using (Html.BeginForm())*@ 



@section scripts { 
    @Scripts.Render("~/bundles/knockout") 
    @*<script src="/Scripts/knockout.mapping.updateData.js"></script>*@ 
    @Scripts.Render("~/bundles/knockout/build/start") 


    <script id="document-ready"> 
     var viewModel = {}; 

     $(function() { 
      pageInit(); 

     }); //document.ready 

    </script> 

    <script id="ko-bind-page-init"> 
     function pageInit() { 

      viewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)), BuildStartViewModelMapping); 
      ko.applyBindings(viewModel); 
      viewModel.errors.showAllMessages(false); //ko.validation init 
     } 
    </script> 

}

Et voici une partie de knockout.mapping.js (~/faisceaux/knock-out/build/départ):

var viewModel = {}; 

var BuildStartViewModel = function (data) { 
    ko.mapping.fromJS(data, BuildStartViewModelMapping, this); 
}; 

var BuildStartViewModelMapping = { 
    //'ignore': ['CoverColorName', 'PaperName', 'CoverColorId'], 
    create: function (options) { 
     var self = new BuildStartViewModel(options.data); 
     ko.BaseViewModel.call(self); 
     ko.BuildCommonViewModel.call(self); 
     self.IsStartView(true); 

     /*=================================================*/ 
     //Custom observables not in data 
     /*=================================================*/ 
     self.AdditionalTextStampingYes = ko.observable(false); 
     self.OriginalProjectName = ko.observable(self.Name()); 
     /*=================================================*/ 

     self.BuildStartBgClassGet = ko.computed(function() { 
      var styleName = self.Style.StyleName().toLowerCase(); 



      return 'build-start-bg-' + styleName; 
     }); 

     self.PageCountEstimated.subscribe(updatePageCount); 

     function updatePageCount() { 
      if (validatePageCountEstimated(self.PageCountEstimated())) { 
       self.PageCount(self.PageCountEstimated()); 
      } 
     } 


     /*=================================================*/ 
     //New Style Selected 
     /*=================================================*/ 
     self.Style.StyleId.subscribe(onStyleIdNew); 

     function onStyleIdNew() { 
      if (!self.Style.StyleId()) 
       return; 

      Application.LoadingDisplayToggle(); 

      var url = $.concatUrl(viewModel.UrlRootGetProjectModel(), viewModel.Style.StyleId()); 

      $.ajax({ 
       url: url, 
       type: 'POST', 
       dataType: 'json', 
       contentType: 'application/json; charset=utf-8', 
       async: true, 
       success: function (data) { 
        if (!data) 
         return; 


        ko.mapping.fromJS(data, BuildStartViewModelMapping, viewModel); 
        viewModel.errors.showAllMessages(false); //ko.validation init 

        //Refresh/Update Style Image 
        var $styleImage = $('#imgDisplayImage'); 
        $styleImage.attr('src', ''); 
        $styleImage.attr('src', data.Style.DisplayImage); 
        $('#hdnimage').val(data.Style.DisplayImage); 

        var $body = $('body'); 

        console.log('TODO: UnComment When we have style images'); 
        //$body.removeClass(); 
        //$body.addClass('cover ' + self.BuildStartBgClassGet()); 

        Application.LoadingDisplayToggle(); 
       }, 
       error: function() { 
        Application.LoadingDisplayToggle(); 
       } 
      }); 
     } 

     /*=================================================*/ 



self.formSubmit = saveData; 

     return self; 

     /*=================================================*/ 
     //saveData/submit 
     /*=================================================*/ 
     function saveData(data, event) { 
      //self.Name.isValidating.subscribe(function (isValidating) { 
      // if (!isValidating && self.errors().length > 0) { 
      //  self.errors.showAllMessages(true); 
      //  return; 
      // } 
      //}); 

      //if (self.isValidating()) { 
      // setTimeout(function() { 
      //  saveData(data, event); 
      // }, 50); 
      // return false; 
      //} 

      // ko.validation check if valid 
      if (self.errors().length > 0) { 
       self.errors.showAllMessages(true); 
       return; 
      } 

      var $form = $(event.currentTarget).closest('form'); 

      if ($form.valid() && self.errors().length === 0) { 
       var copy = ko.toJS(this); 
       delete copy.errors; 
       delete copy.__ko_mapping__; 

       $.ajax({ 
        url: $form.attr('action'), 
        type: 'POST', 
        dataType: 'json', 
        data: ko.toJSON(copy), 
        contentType: 'application/json; charset=utf-8', 
        success: function (response) { 

         var url = self.UrlWithIdUploadStep(); 
         url = url.substr(0, url.lastIndexOf("/")); //remove id (could be StyleId and not ProjectId if new project) 
         url = $.concatUrl(url, response); //add project id to url, could be existing or new ProjectId 

         window.location.href = url; 
        }, 
        beforeSend: function() { 
         self.PricingPartialSubmitLock(true); 
         Application.LoadingDisplayToggle(); 
        }, 
        error: function (result, error, errorThrown) { 
         self.PricingPartialSubmitLock(false); 
         Application.LoadingDisplayToggle(); 
         Application.ToastrError(result.responseText); 
        } 
       }); 
      } 

      return false; 
     }; 

    } 

}; 

Et voici Scripts/knockout.mapping.updateData.js, je ne pense pas que vous en aurez besoin pour commencer avec ce modèle mais j'inclus au cas où:

/* 
* Extension to the knockoutjs mapping plugin 
* http://github.com/janhartigan/knockout-mapping-updatedata 
* Requires KnockoutJS and the mapping plugin 
* 
* Dual licensed under the MIT or GPL Version 2 licenses. 
* Jan Hartigan 
*/ 
(function() { 
    /** 
    * A function that lets you "update from js" without overriding all the view model properties and methods. You just need to supply 
    * the viewModel, the original JS model on which you based your data (typically what you'd use in the mapping fromJS method), and the new JS 
    * object that has the updated information. 
    * 
    * @param Object viewModel 
    * @param Object dataModel 
    * @param Object jsObject 
    * 
    * @return Object (returns the viewModel) 
    */ 
    ko.mapping.updateData = function(viewModel, dataModel, jsObject) { 
     if (arguments.length < 3) throw new Error("When calling ko.updateData, pass: the view model, the data model, and the updated data."); 
     if (!viewModel) throw new Error("The view model is undefined."); 

     for (var i in dataModel) { 
      if (i in jsObject && i in viewModel && typeof dataModel[i] != 'function') { 
       viewModel[i](jsObject[i]); 
      } 
     } 

     return viewModel; 
    } 

    ko.exportSymbol('mapping.updateData', ko.mapping.updateData); 
})();