none
Knock Out Js Y Parciales Dinamicas RRS feed

  • Pregunta

  • Hola

    Me encuentro desarrollando una aplicación en donde cada vez que hago click en un botón ejecuto el siguiente código js:

    function NewBilling() {
                $.post('@Url.Action("NewBilling", "Bill", new { area = "Billing" })', function (data) {
                    BuildDialogBilling(data);
                });
            }

    Lógicamente luego ejecuto la siguiente función:

    function BuildDialogBilling(dataRetrieved) {
    
                var billingId = $(dataRetrieved).find("#hdfBillWindowId").val();
                var billingCode = $(dataRetrieved).find("#hdfBillCode").val();
                $("#divContainerHelper").html(dataRetrieved);
                $("#divBillWindow-" + billingId).dialog({ appendTo: $("#divMainBillingContainer"), title: "Factura No. " + billingCode, width: '85%', resizable: false, });
                $("#divContainerHelper").html("");
            }

    El siguiente es el código de la vista parcial:

    @model Cms.Spv.Entities.Dto.BillingBillingDetail
    
    <div id="divBillWindow-@Model.Billing.Id" style="padding: 2%" >
        <section id="BillMainIdentifierSection-@Model.Billing.Id">
            <input type="hidden" id="hdfBillWindowId" name="BillWindow" value="@Model.Billing.Id" />
            <input type="hidden" id="hdfBillCode" name="BillWindow" value="@Model.Billing.Code" />
        </section>
        <table style="width: 100%">
            <tr>
                <td style="width: 25%">
                    <table style="width: 100%">
                        <tr>
                            <td>
                                <label>Fecha</label>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <input style="width: 100%" type="text" readonly name="CreationDate" id="txtCreationDate" value="@Model.Billing.CreationDate.Value.ToLongDateString()"/>
                                <br />
                                <br />
                            </td>
                        </tr>
                    </table>
                </td>
                <td style="width: 5%"></td>
                <td style="width: 25%">
                    <table style="width: 100%">
                        <tr>
                            <td>
                                <label>Cliente</label>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <input style="width: 100%" type="text" readonly name="clientName" id="txtClientName" />
                                <input type="hidden" name="ClientId" id="hdfClientId" value="@Model.Billing.ClientId"/>
                                <br />
                                <br />
                            </td>
                        </tr>
                    </table>
                </td>
                <td style="width: 5%"></td>
                <td style="width: 25%">
                    <table style="width: 100%">
                        <tr>
                            <td>
                                <label>Referencia de factura</label>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <input style="width: 100%" type="text" readonly name="Code" id="txtCode" value="@Model.Billing.Code"/>
                                <br />
                                <br />
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
            <tr style="vertical-align: top">
                <td>
                    <section id="FirstColumnaMainAcctionsSecction-@Model.Billing.Id">
                        <table style="width: 100%;">
                            <tr>
                                <td>
                                    <button type="button" class="easyui-linkbutton" style="width: 100%">Buscar cliente (Ctrl + 1)</button>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <button type="button" class="easyui-linkbutton" style="width: 100%" data-bind="click: SeachProductCommand">Buscar producto (Ctrl + 2)</button>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <button type="button" class="easyui-linkbutton" style="width: 100%" onclick="return NewBilling();">Realizar nueva venta (Ctrl + 3)</button>
                                </td>
                            </tr>
                        </table>
                    </section>
                </td>
                <td style="width: 5%"></td>
                <td>
                    <table style="width: 100%">
                        <tr>
                            <td>
                                <button type="button" class="easyui-linkbutton" style="width: 100%">Minimizar (Ctrl + 4)</button>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <button type="button" class="easyui-linkbutton" style="width: 100%">Facturar (Ctrl + 5)</button>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <button type="button" class="easyui-linkbutton" style="width: 100%">Retener (Ctrl + 6)</button>
                            </td>
                        </tr>
                    </table>
                </td>
                <td style="width: 5%"></td>
                <td>
                    <table style="width: 100%">
                        <tr>
                            <td>
                                <button type="button" class="easyui-linkbutton" style="width: 100%">Anular (Ctrl + 7)</button>
                            </td>
                        </tr>
                        <tr>
                            <td></td>
                        </tr>
                        <tr>
                            <td></td>
                        </tr>
                    </table>
                </td>
            </tr>
            <tr>
                <td colspan="5">
                    <section id="ProductChoosenSection-@Model.Billing.Id">
                        <table style="width: 100%;">
                            <tr>
                                <td colspan="2">
                                    <label>
                                        Producto
                                    </label>
                                </td>
                                <td style="width: 5%"></td>
                                <td>
                                    <label>
                                        Stock
                                    </label>
                                </td>
                                <td>
                                    <label>
                                        Precio a la venta
                                    </label>
                                </td>
                                <td style="width: 5%"></td>
                                <td>
                                    <label>
                                        Porcentaje de ganancia
                                    </label>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="2">
                                    <input type="text" name="ProductName" id="txtProductName" style="width: 100%; text-align: center" readonly />
                                </td>
                                <td></td>
                                <td>
                                    <input type="text" name="Stock" id="txtStock" style="text-align: center" readonly />
                                </td>
                                <td>
                                    <input type="text" name="PublicCost" id="txtPublicCost" style="text-align: center" onkeypress="return KeyPressOnlyNumbers(event)" />
                                </td>
                                <td style="width: 5%"></td>
                                <td>
                                    <input type="text" name="WinningPercentage" id="txtWinningPercentage" style="text-align: center" onkeypress="return KeyPressOnlyNumbers(event)" />
                                </td>
                            </tr>
                            <tr>
                                <td colspan="5">
                                    <label>Código de producto</label>
                                </td>
                                <td></td>
                                <td>
                                    <label>Cantidad</label>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="5">
                                    <input type="text" name="ProductCode" id="txtProductCode" style="width: 100%; text-align: center" data-bind="numeric: number, value: ProductCode" />
                                </td>
                                <td></td>
                                <td>
                                    <input type="text" name="Quantity" id="txtQuantity" style="text-align: center" data-bind="numeric: number, value: ProductQuantity" />
                                </td>
                            </tr>
                        </table>
                    </section>
                </td>
            </tr>
            <tr>
                <td colspan="5">
                    <label>Detalles</label>
                    <table style="width: 100%">
                        <tr>
                            <td></td>
                        </tr>
                    </table>
                </td>
            </tr>
            <tr>
                <td colspan="5" style="vertical-align: bottom">
                    <label>Observaciones</label>
                    <textarea style="width: 100%" name="Observation" id="txtObservation">@Model.Billing.Observation</textarea>
                </td>
            </tr>
        </table>
    </div>
    
    <script type="text/javascript" language="javascript">
    
        ko.bindingHandlers.numeric = {
            init: function (element, valueAccessor) {
                $(element).on("keydown", function (event) {
                    // Allow: backspace, delete, tab, escape, and enter
                    if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
                        // Allow: Ctrl+A
                        (event.keyCode == 65 && event.ctrlKey === true) ||
                        // Allow: . ,
                        (event.keyCode == 188 || event.keyCode == 190 || event.keyCode == 110) ||
                        // Allow: home, end, left, right
                        (event.keyCode >= 35 && event.keyCode <= 39)) {
                        // let it happen, don't do anything
    
                        console.log(element);
                        return;
                    }
                    else {
                        // Ensure that it is a number and stop the keypress
                        if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
                            event.preventDefault();
                        }
                    }
                });
            }
        };
    
        var theMainModel = {
            SeachProductCommand: function () {
                console.log(theBillModel.BillId);
                console.log(theBillModel.BillCode);
            }
        };
    
        var theProductModel = {
            ProductCode: ko.observable(""),
            ProductQuantity: ko.observable(""),
    
        };
    
        var theBillModel = {
            BillId: ko.observable(""),
            BillCode: ko.observable("")
        };
    
        $(document).ready(function () {
    
            theBillModel.BillId = $("#hdfBillWindowId").val();
            theBillModel.BillCode = $("#hdfBillCode").val();
    
            ko.applyBindings(theProductModel, $("#ProductChoosenSection-" + theBillModel.BillId)[0]);
            ko.applyBindings(theBillModel, $("#BillMainIdentifierSection-" + theBillModel.BillId)[0]);
            ko.applyBindings(theMainModel, $("#FirstColumnaMainAcctionsSecction-" + theBillModel.BillId)[0]);
    
            $("#hdfBillWindowId").remove();
            $("#hdfBillCode").remove();
        });
    
    </script>
    

    El problema es que al hacer click en un boton y me ejecute el codigo KnockOut Js siempre me sale informacion de la ultima parcial a la cual le aplique modelo de Knockout:

    var theMainModel = {
            SeachProductCommand: function () {
                console.log(theBillModel.BillId);
                console.log(theBillModel.BillCode);
            }
        };

    Y lo cual pierdo referencia a los datos de vistas parciales abiertas con anterioridad ... Necesito que si tengo n vistas parciales abiertas entonces por cada parcial se mantenga el modelo que construi por Knockout js ... Pues al abrir una nueva parcial se pierde referencia al modelo de las parciales anteriores, es decir las lineas de "console.log" siempre me van a mostrar la informacion de la ultima parcial cargada y necesito que cada parcial mantenga la información del modelo ... Estoy usando la tecnologia inapropiada, deberia usar Angular JS ??

    Saludos !!

    martes, 16 de diciembre de 2014 17:41

Todas las respuestas

  • el codigo de la funcion BuildDialogBilling() es incorrecto, no veo porque usas

    var billingId = $(dataRetrieved).find("#hdfBillWindowId").val();

    deberias enviar un json como respuesta algo como ser

    public class BillController : Controller {
    
       [HttpPost]
        public JsonResult NewBilling(){
    
          //aqui retornas un json
    
       }
    
    }

    al devolver un json puede asignar directo sin tener que usar jquery

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    martes, 16 de diciembre de 2014 18:09
  • analizando la view no entiendo, la primer parte donde explicas los del $.post donde lo usas ?

    >>Necesito que si tengo n vistas parciales abiertas entonces por cada parcial se mantenga el modelo que construi por Knockout js

    Knockout ni Angular logran eso de form directa

    lo que tu necesitas es desarrollar una aplicacion estilo SPA (Single Page Application)

    entonces mantienes el mismo controller (si usas angular) o viewmodel (si usas knockout ) y vas cambiando de view y navegando sin navegar entre paginas

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 16 de diciembre de 2014 18:20
  • Hola

    Estas diciendo que si quiero tener modales inline contenidas en un div como muestro la imagen a continuación:

    (Verdes: Modales, Azul: Template, Naranja: Menu)

    No puedo usar un patrón MVVM por cada modal ? Sino que tengo que usar SPA ??

    PD: Este código: var billingId = $(dataRetrieved).find("#hdfBillWindowId").val();

    Lo usaba por que quería saber y encontrar cual era como el identificador del div de mi parcial, al retornar una parcial hacia:

    [HttpPost]
            public ActionResult NewBilling()
            {
                var newBilling = MainFacadeSpv.BillingService.PrepareNewBilling(User.Entity.Id);
                return PartialView("~/Areas/Billing/Views/Bill/_PartialBill.cshtml", newBilling);
            }

    Y por eso hacia:

    $.post('@Url.Action("NewBilling", "Bill", new { area = "Billing" })', function (data) {
                    BuildDialogBilling(data);
                });
    Al cargarse el formulario, es decir en el:
    $(document).ready(function () {

    martes, 16 de diciembre de 2014 19:33
  • >>(Verdes: Modales, Azul: Template, Naranja: Menu)

    a que te refieres con modales ? son popup de jquery

    >>No puedo usar un patrón MVVM por cada modal ?

    puedes usarlo pero si descargas la pagina el viewmodel se ira con este, no se mantiene los estados si cambias de pagina

    >>Sino que tengo que usar SPA ?

    si la idea es moverse entre varias paginas y mantener la info en el viewmodel o controller entonces si

    es mas para desarrollar el concepto de SPA requieres de knockout o angular

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 16 de diciembre de 2014 21:26
  • Hola

    Efectivamente, modales son de JQuery (Dialog), por cada dialog requiero que me persista una instancia del modelo que diseñe en knockout ...

    Si no puedo soportar una instancia del modelo por cada dialog, entonces sugieres que use SPA ???

    martes, 16 de diciembre de 2014 22:26
  • hola

    bien entonces modales son popup de jquery

    pero entonces porque tienen menu ? es algo raro que un popup tenga menu

    los verdes entiendo serian template, pero no queda claro como trabajan si es que sera estilo wizard en donde pueden ir pasando varias de las pantallas verdes tomando diferentes datos

    o si aparece una pantalla verde persiste, y luego otra independinte y tambien persiste, porque si es asi cada verde podria tener su propio viewmodel o controller, no tiene porque usar la que defina la azul

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 16 de diciembre de 2014 22:43
  • Hola

    El fondo azul es el body y el naranja es el menú del sitio, los cuadros verdes son modales, dialogs, popup, etc ... Las cuales les hago append a otro div (este div esta como contenedor de modales en una pagina). Ahora bien, lo que trato de lograr es homologo a lo que era los MDI en Windows Forms, por eso digo que cada PopUp contiene una partial view y que dicha partial contiene un modelo de knockout js que persista y que cuando abra otra modal con la misma partial aunque el modelo es igual, pues lógicamente los datos sean diferentes ya que es una nueva instancia del modelo.

    Pero lo que pasa es que cada vez que abro la modal, dialog, popup, el modelo se superpone y se pierde referencia a los datos de la popUp abierta previamente.

    En conclusión lo que trato es un MDI de Windows Forms, pero sin controlar el instanciamiento único de modales sino que cada nueva instancia de la modal sea diferente ...

    Espero me halla hecho entender ...

    martes, 16 de diciembre de 2014 23:12
  • >>El fondo azul es el body y el naranja es el menú del sitio, los cuadros verdes son modales, dialogs, popup, etc ..

    ahh ok, pense que el azul tambien era un popup

    >>por eso digo que cada PopUp contiene una partial view y que dicha partial contiene un modelo de knockout js que persista y que cuando abra otra modal con la misma partial aunque el modelo es igual, pues lógicamente los datos sean diferentes ya que es una nueva instancia del modelo.

    habria que ver como defines los viewmodel de los popup, imagino que creas nuevos por cada inject de html que haces del partialview en el div del popup

    quizas debas crear un viewmodel nuevo cada vez que cargas el popup, por supuesto habria que validar que se descargue ese javascript

    >>En conclusión lo que trato es un MDI de Windows Forms,

    una desarrollo SPA tiende justamente a eso, dale una mirada al tema para ver si te convence, ojo no digo que sea algo simple, es una forma de diseño web que hay que aprender, pero el VS tiene template para poder encarar un desarrollo SPA

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    miércoles, 17 de diciembre de 2014 4:51
  • Hola

    El código que muestro a continuación se ejecuta cuando se termina de cargar la partial view (Este código esta contenido en la partial view) ... 

    <script type="text/javascript" language="javascript">
        
        var theMainModel = {
            SeachProductCommand: function () {
                console.log(theBillModel.BillId);
                console.log(theBillModel.BillCode);
            }
        };
    
        var theProductModel = {
            ProductCode: ko.observable(""),
            ProductQuantity: ko.observable(""),
    
        };
    
        var theBillModel = {
            BillId: ko.observable(""),
            BillCode: ko.observable("")
        };
    
        $(document).ready(function () {
    
            theBillModel.BillId = $("#hdfBillWindowId").val();
            theBillModel.BillCode = $("#hdfBillCode").val();
    
            ko.applyBindings(theProductModel, $("#ProductChoosenSection-" + theBillModel.BillId)[0]);
            ko.applyBindings(theBillModel, $("#BillMainIdentifierSection-" + theBillModel.BillId)[0]);
            ko.applyBindings(theMainModel, $("#FirstColumnMainAcctionsSecction-" + theBillModel.BillId)[0]);
    
            $("#hdfBillWindowId").remove();
            $("#hdfBillCode").remove();
        });
    
    </script>

    Al final del script es cuando inyecto los modelos ...

    La cuestión es que cada vez que lanzo un nuevo dialog todos los dialogs anteriormente abiertos quedan con la información del ultimo dialog abierto ... Como evito esto ??

    Me esta tentando SPA y por cada nueva pagina abierta pues persiste el modelo con su información ... Si tengo n paginas abiertas con un mismo modelo pero diferentes datos (información) por cada pagina supongo que es homologo cuando abria en Windows Forms un formulario y cada nueva instancia del form a pesar que le atachaba un el mismo modelo pues los datos eran diferentes ...

    PD: Me confirmas si estoy en lo correcto o no ...



    miércoles, 17 de diciembre de 2014 23:35