2016-04-23 5 views
0

Ich versuche, einzelne Elemente eines Arrays zu bearbeiten. Ich habe einen JSON-Array wie weiter:Klicken Sie auf ein DIV anwenden Dinamic Datenbindung, um das CSS mit einem HTML-Eingang bearbeiten - knockout.js

[ {"idComponent":1,"left":"100px","top":"100px","idHTML":"name_div","width":"200px","height":"300px","value":"My name is"} 
       ,{"idComponent":2,"left":"200px","top":"200px","idHTML":"date_div","width":"200px","height":"300px","value":"2016-Enero-12"} 
       ,{"idComponent":3,"left":"300px","top":"300px","idHTML":"weigth_div","width":"200px","height":"300px","value":"1.5 KG"} 
       ,{"idComponent":4,"left":"400px","top":"400px","idHTML":"talla_div","width":"200px","height":"300px","value":"23"} 
       ,{"idComponent":5,"left":"500px","top":"500px","idHTML":"description_div","width":"300px","height":"300px","value":"The text"} 
      ] 

diese Observablen in Knockout umgewandelt werden. Jeder wird an ein DIV-Element gebunden, das auf dem Bildschirm angezeigt werden soll. "left", "top", "height" und "width" sind CSS-Attribute, die auf jedes angewendet werden.

Wenn Sie eines der DIV-Container mit der Maus anklicken, versuche ich, das Element an HTML-Eingaben zu binden, um die CSS-Werte zu bearbeiten. Sie können die Idee im nächsten Bild sehen:

Mockup Image - Click here to see the image

Der Code ist der nächste:

function convertPixelsToInches(pixels){ 
    return pixels/96; 
    } 

    // Elemento regresados desde el servidor. 
    var dataFromServer = 
    { 
    "idTemplate":"1" 
    ,"components" : 
     [{"idComponent":1,"left":"100px","top":"100px","idHTML":"name_div","width":"200px","height":"300px","value":"Sergio Pinto Fernandez"} 
     ,{"idComponent":2,"left":"200px","top":"200px","idHTML":"date_div","width":"200px","height":"300px","value":"2016-Enero-12"} 
     ,{"idComponent":3,"left":"300px","top":"300px","idHTML":"weigth_div","width":"200px","height":"300px","value":"1.5 KG"} 
     ,{"idComponent":4,"left":"400px","top":"400px","idHTML":"talla_div","width":"200px","height":"300px","value":"23"} 
     ,{"idComponent":5,"left":"500px","top":"500px","idHTML":"description_div","width":"300px","height":"300px","value":"Tomar dos cucharadas cada 3 hras."} 
     ] 
    ,"paperSize":"papersize_USLetter_portrait" 
    ,"templateImage":{ 
     "imageUrl":"images/SolicitudLaboratorioExpress.jpg" 
     ,"width":"8.5in" 
     ,"height":"11in" 
     ,"left":"0px" 
     ,"top":"0px" 
    } 
    }; 

    function componentModel(dataComponent) { 
    if (!dataComponent) { 
     dataComponent = {}; 
    } 

    var self = this; 
    self.idComponent = ko.observable(dataComponent.idComponent); 
    self.left   = ko.observable(dataComponent.left); 
    self.top   = ko.observable(dataComponent.top); 
    self.idHTML  = ko.observable(dataComponent.idHTML); 
    self.width  = ko.observable(dataComponent.width); 
    self.height  = ko.observable(dataComponent.height); 
    self.value  = ko.observable(dataComponent.value); 
    } 

    /** 
    * data Json from server. 
    * 
    */ 
    function templateModel(data) { 
    if (!data) { 
     data = {}; 
    } 
    var self = this; 

    self.components = ExtractComponents(self, data.components, componentModel); 

    self.currentSelectedComponent = ko.observable(); 
    self.currentSelectedComponentIndex = ko.observable(-1); 

    //self.currentSelectedComponentLeft = ko.observable(); 
    self.currentSelectedComponentLeft = ko.computed(function(){ 
     var value = self.currentSelectedComponentIndex(); 
     console.log(typeof value); 
     //value=value*1; 
     console.log(value); 
     if (value) { 
     return "TT"; 
     } 

     // Get "200px y must save as 200" 
     //return self.currentSelectedComponent().left;//.substring(0,data.length-2); 
     return "FF"; 
    }); 
    self.currentSelectedComponentTop = ko.observable(); 
    self.editComponent = function(component,index){ 
     self.currentSelectedComponentIndex(index); 
     self.currentSelectedComponent(component); 

     // Binding the component to the editor. 
     // ?? 
    }; 
    function bindComponentToEditor() { 
     ko.applyBindings() 
    } 


    self.idTemplate = ko.observable(data.idTemplate); 
    self.paperSize = ko.observable(data.paperSize); 

    /* */ 
    self.paperSizeWidth = ko.observable(convertPixelsToInches(1067)); 
    self.paperSizeHeigth = ko.observable(convertPixelsToInches(1067)); 
    // 
    self.templateImage_imageUrl = ko.observable(data.templateImage.imageUrl); 
    self.templateImage_width = ko.observable(data.templateImage.width); 
    self.templateImage_height = ko.observable(data.templateImage.height); 
    self.templateImage_left = ko.observable(data.templateImage.left); 
    self.templateImage_top = ko.observable(data.templateImage.top); 
    } 

    /** 
    * parent: referencia al objeto o funcion que mando a llamar esta fucnion. 
    * 
    * dataArr: Array de elementos que se desea la funcion ExtractComponents haga mapeo. 
    * Ejemplo de dataArr: 
    * 
    *  [ {"idComponent":1,"left":"100px","top":"100px","idHTML":"name_div","width":"200px","height":"300px","value":"Sergio Pinto Fernandez"} 
      ,{"idComponent":2,"left":"200px","top":"200px","idHTML":"date_div","width":"200px","height":"300px","value":"2016-Enero-12"} 
      ,{"idComponent":3,"left":"300px","top":"300px","idHTML":"weigth_div","width":"200px","height":"300px","value":"1.5 KG"} 
      ,{"idComponent":4,"left":"400px","top":"400px","idHTML":"talla_div","width":"200px","height":"300px","value":"23"} 
      ,{"idComponent":5,"left":"500px","top":"500px","idHTML":"description_div","width":"300px","height":"300px","value":"Tomar dos cucharadas cada 3 hras."} 
     ] 
    * 
    * modelConstructor: funcion con que se creara un nuevo componente, es decir el modelo. 
    * 
    */ 
    function ExtractComponents(parent, dataArr, modelConstructor) { 
    var components = []; 
    if (dataArr == null) { 
     return components; 
    } 

    for (var i = 0; i < dataArr.length; i++) { 
     var dataArrElement = dataArr[i]; 
     var component = new modelConstructor(dataArrElement,parent); 
     components.push(component); 
    } 
    return components; 
    } 

    ko.applyBindings(new templateModel(dataFromServer)); 

Ich habe zwei Probleme: 1. Der Eingang für die linken und oberen Werte nur ganzzahlige akzeptieren Werte, die i "200px" bis 200 müssen String aber alle Tage erhalte ich einen Fehler:

self.currentSelectedComponentLeft = ko.computed(function(){ 
     var value = self.currentSelectedComponentIndex(); 
     console.log(typeof value); 
     //value=value*1; 
     console.log(value); 
     if (value) { 
     return "TT"; 
     } 

     // Get "200px and save as 200" 
     //return self.currentSelectedComponent().left;//.substring(0,data.length-2); 
     return "FF"; 
    }); 
".left nicht definiert ist"
  1. Das Hauptproblem ... Wie kann ich das DIV-Element binden, wenn ich das Element auf die Eingänge anschließe? Ich denke, ich brauche Dinamic Binding oder Dinamic-Abonnement, kann aber keine Antwort auf dieses Problem der dynamischen doppelten Datenbindung finden.

Dies ist der HTML:

<div id="mainContainer"> 
    <div id="contentPrint_div" class="page" data-bind="css: paperSize"> 

    <img id="template_img" data-bind="attr: {src: templateImage_imageUrl}, 
     style: {width: templateImage_width, height: templateImage_height, left: templateImage_left, top: templateImage_top}"> 

    <div id="fieldsArea_div" class="" data-bind="foreach: components"> 
     <div class="field" data-bind="html: value, style: {width: width, left:left, top:top}, 
     attr: {id: idHTML}, click: $parent.editComponent($data,$index)"></div> 
    </div> 
    </div> 

    <div id="toolsbar"> 
    <div id="toolbarPanel"> 
     ID template:<span data-bind='text: idTemplate'></span> 

     <div id="panelMenuInfoElements_div"> 
     Elemento actual: <span data-bind='text: idTemplate'></span> 
     Posicion 
     X:<input type="text" class="form-control" id="" placeholder="x" min="0" step="0.01" 
      data-bind="attr: {max: paperSizeWidth}, value: currentSelectedComponentTop"> 
     Y:<input type="text" class="form-control" id="" placeholder="y" min="0" step="0.01" 
      data-bind="attr: {max: paperSizeHeigth}, value: currentSelectedComponentLeft"> 
     </div> 

    </div> 
    <div id="toolbarCode"> 
     <pre data-bind="text: ko.toJSON($root, null, 2)"></pre> 
    </div> 

    </div> 
</div> 
+0

Für Ihr px Problem in der Bindung dieser Arbeit sollte - Stil: {links: links + 'px'} – dmoo

+0

Wenn die doppelten Daten gearbeitet Bindung, was es tun würde? Dies ist kein jQuery, Sie müssen also nichts auswählen, um es zu binden. Benötigen Sie eine CSS-Änderung oder Daten oder was? – brianlmerritt

+0

@ dmoo gute Idee, aber nach dem Lesen der user3297291 Antwort Ich denke, dass es in eine berechnete Funktion sein muss. – Sergio

Antwort

0

Sie einige Code ganz geschrieben; Ich bin mir nicht 100% sicher, ob ich alle Fragen richtig beantwortet habe. Aber ich habe versucht, ein Beispiel zu schaffen, von dem ich denke, dass es zeigt, wie man seine Probleme löst.

  • Ich habe ein computed verwendet, um ein style Objekt zu erstellen, die x und y Observablen umschreibt, die Zahlen sind, auf die style kompatibel Bindung: { top: 0px, left: 0px }
  • ich verwendet habe, ein with Bindung Ihre <input> Elemente zu verknüpfen der zuletzt angeklickte Block

var Block = function(name, x, y) { 
 
    this.label = name; 
 
    this.x = ko.observable(x); 
 
    this.y = ko.observable(y); 
 

 
    this.style = ko.computed(function() { 
 
    return { 
 
     top: this.y() + "px", 
 
     left: this.x() + "px" 
 
    } 
 
    }, this); 
 
} 
 

 

 
var VM = function() { 
 

 
    this.blocks = [ 
 
    new Block("Block 1", 100, 100), 
 
    new Block("Block 2", 200, 100), 
 
    new Block("Block 3", 300, 100), 
 
    ]; 
 

 
    this.selectedBlock = ko.observable(this.blocks[0]); 
 
}; 
 

 
ko.applyBindings(new VM());
.Block { 
 
    position: absolute; 
 
    background: red; 
 
    padding: 1rem; 
 
    list-style: none; 
 
} 
 
.Block.is-selected { background: yellow; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<div class="Inputs" data-bind="with: selectedBlock"> 
 
    <div> 
 
    Editing <span data-bind="text: label"></span> 
 
    </div> 
 
    <div>Left: 
 
    <input type="number" data-bind="value: x"> 
 
    </div> 
 
    <div>Top: 
 
    <input type="number" data-bind="value: y"> 
 
    </div> 
 
</div> 
 

 
<ul data-bind="foreach: blocks"> 
 
    <li class="Block" data-bind=" 
 
    click: $parent.selectedBlock, 
 
    style: style, 
 
    text: label, 
 
    css: { 'is-selected': $data == $parent.selectedBlock()}"></li> 
 
</ul>

+0

Mein Gut !! Ich verbringe 10 Stunden damit, es zu versuchen. Ist mein erstes Mal mit Knockout. Ja, ich schreibe so viel Code, sorry, aber ich dachte, dass der vollständige Code helfen könnte, die Idee zu verstehen, dass der Block dynamisch erstellt wird, ich werde meine Frage später ändern. – Sergio

+0

Sie sind ein Genie, jeder Block muss ein Computerobjekt besitzen, um seinen Stil zu verwalten. Ich werde den JSON vom Server nur auf Zahlen ändern, z. B. 200px auf nur 200. Ich wusste nicht, ich könnte dies tun: "click: $ parent.selectedBlock", dies bindet einen Block mit den Eingängen O.o. Ich verstehe nicht, wie das passiert ist, ist automatisch ich denke. Danke !! – Sergio

+0

Das Snippet ist Teil von Stackoverflow? – Sergio