2012-07-13 14 views
5

Estoy usando knockoutjs para crear una vista en árbol de las divisiones. Junto a cada nodo habrá tres botones: 1) Nuevo elemento secundario (se aplica al nodo que está junto a 2) Eliminar (Esto elimina el nodo que está junto a, y 3) Copiar, que copia el nodo y todos sus elementos secundarios y crea un nuevo nodo debajo del padre.Quitar el yo de Observable Array en el knockout JS

Tengo el botón Nuevo presionado, y ahora estoy trabajando en el botón Eliminar. Parece que no puedo hacer que funcione, y en lugar de hacer algo útil, simplemente refresca toda la página. Aquí está el código:

Vista:

<h2>Skill & Weight Divisions</h2> 
     <span data-bind="text: tournamentname"></span><button data-bind="click: addDivision"><img src="new.png"/></button> 
     <ul data-bind="template: { name: 'divisionTemplate', foreach: divisions }"></ul> 

Plantilla:

<script id="divisionTemplate" type="text/html"> 
    <li data-bind="style: {'background-color':color}"> 
     <input data-bind="value: name"/><button data-bind="click: addDivision"><img src="new.png"/></button><button data-bind="click: $parent.removeDivision"><img src="remove.png"/></button><button data-bind="click: $parent.copyDivision"><img src="copy.png"/></button> 
     <ul data-bind="template: { 'if': children, name: 'divisionTemplate', foreach: children }"></ul> 
    </li>  
</script> 

Vista del modelo y de la función de ayuda apropiado:

function division(id, name, filter, children) { 
     this.id = ko.observable(id); 
     this.name = ko.observable(name); 
     this.filter = ko.observable(filter) 
     if(children){ 
      this.children = ko.observableArray(children); 
     }else{ 
      this.children = ko.observableArray(); 
     } 
     this.addDivision = function(){ 
      this.children.push(new division("", "", "")); 
     } 
     this.removeDivision = function(division){ 
      this.children.remove(division); 
     } 
     this.copyDivision = function(division){ 
      this.children.push(division); 
     } 
     this.color = randColor(); 
    }; 
    function tournamentViewModel(){ 
     var self= this; 
     self.tournamentname = ko.observable('NO NAME YET'); 
     self.districts = ko.observableArray([new district('Provo',1),new district('Salt Lake City',2),new district('St. George',3)]); 
     self.district = ko.observable(self.districts()[0]); 
     self.regions = ko.observableArray([new region('Utah',1),new region('Idaho',2)]); 
     self.region = ko.observable(self.regions()[0]); 
     self.location = ko.observable('WHEREVER YOU WANT'); 
     self.eventdate = ko.observable(''); 
     self.startTime = ko.observable(''); 
     self.image = ko.observable(); 
     self.flyer = ko.computed(function(){ 
      var flyerHTML = '<span style="text-align:center;padding:10px;"><h1>'+self.tournamentname()+'</h1><img src="'+self.image()+'"/><br/>'; 
      flyerHTML += 'District: ' + self.district().districtName + ' Region: ' + self.region().regionName+'<br><br>'; 
      flyerHTML += '<h2>WHEN: '+self.eventdate()+' '+self.startTime()+'</h2>'; 
      flyerHTML += '<h2>WHERE: '+self.location()+'</h2>'; 
      flyerHTML += '<img src="http://maps.googleapis.com/maps/api/staticmap?center='+encodeURI(self.location())+'&zoom=12&size=200x200&markers=color:blue%7Clabel:S%7C'+encodeURI(self.location())+'&maptype=roadmap&sensor=false"/>'; 
      return flyerHTML; 
     }, self); 
     self.clearImage = function(){ 
      self.image(''); 
     } 
     self.tournamentID = ko.computed(function(){return 't_'+self.district()+'_'+self.region()+'_'+self.eventdate()}, self); 
     self.pricingStructures = ko.observableArray([new pricingStructure(3,2.99), new pricingStructure(1,1.99)]); 
     self.removePricingStructure = function(pricingStructure){ 
      self.pricingStructures.remove(pricingStructure); 
     } 
     self.addPricingStructure = function(){ 
      self.pricingStructures.push(new pricingStructure("", "")); 
     } 
     self.promoCodes = ko.observableArray(); 
     self.promoTypes = ['%','$']; 
     self.removePromoCode = function(promoCode){ 
      self.promoCodes.remove(promoCode); 
     } 
     self.addPromoCode = function(){ 
      self.promoCodes.push(new promoCode("", ""));  
     } 
     self.divisions = ko.observableArray([new division(1, "Men","",[new division(2,"Gi"), new division(3,"No-Gi")])]); 
     self.addDivision = function(){ 
      self.divisions.push(new division("", "", "")); 
     } 

    } 
    ko.applyBindings(new tournamentViewModel()); 

Mi pregunta principal en todo esto es la siguiente: ¿Hay alguna manera de acceder a la matriz principal de un objeto para eliminar ese mismo objeto de la matriz? Gracias de antemano por la ayuda!

EDITAR: Aquí hay un jsFiddle: http://jsfiddle.net/eqY7Z/ Sin embargo, parece que no funciona en absoluto. Si ustedes no pueden hacerlo funcionar, incluiré el enlace a mi sitio donde se está alojado para que puedan echarle un buen vistazo.

+0

También me gustaría añadir que en algún momento obtuve la eliminación trabajando, pero solo dos niveles más abajo. Algo más profundo no funcionó.Si puedo recordar el código que funcionó allí, te lo haré saber. –

+1

¿Puedes crear un jsfiddle para esto? – HashCoder

+0

Tengo que ir a trabajar ahora, pero en mi descanso voy a poner uno. –

Respuesta

2

Tomé su idea e hice un working fiddle, que se comporta exactamente como lo describió. No quería tratar de resolver el tuyo, lo siento. Tenía muchas cosas que no estaban directamente relacionadas con su problema, y ​​esta solución es lo suficientemente general como para que otras personas puedan usarla. Si necesita ayuda para adaptarlo, avíseme.

Una cosa a tener en cuenta es la función de clonación. Su función de copia no es profunda y dará como resultado múltiples nodos que apuntan al mismo objeto. Si tuviera que actualizar un valor de nodos, se propagaría a sus clones. Knockout proporciona una útil copia profunda + desempaquetar observables con ko.toJS. Súper útil.

Los JS:

var Node = function(name, children) { 
    var self = this; 
    self.name = ko.observable(name || 'NewNode'); 
    self.children = ko.observableArray(
    ko.utils.arrayMap(children || [], function(i) { 
     return new Node(i.name, i.children); 
    })); 
    self.newChild = function() { 
     self.children.push(new Node()); 
    }; 
    self.removeNode = function(node) { 
     self.children.remove(node); 
    }; 
    self.copyNode = function(node) { 
     var cloneNode = ko.toJS(node); 
     self.children.push(new Node(cloneNode.name, cloneNode.children)); 
    }; 
}; 

//Example data removed for brevity, see fiddle 
ko.applyBindings(new Node(data.name, data.children));​ 

HTML:

<button data-bind="click: newChild">NewNode</button> 
<ul data-bind="template: { name: 'treeTemplate', foreach: children}"> 
</ul> 

<script id="treeTemplate" type="text/html"> 
    <li> 
     <input data-bind="value: name" /> 
     <button data-bind="click: newChild">New Child</button> 
     <button data-bind="click: $parent.removeNode">Remove Node</button> 
     <button data-bind="click: $parent.copyNode">Copy Node</button> 
     <ul data-bind="template: { name: 'treeTemplate', foreach: children}"></ul> 
    </li> 
</script> 
​ 
+0

Esto se ve genial y lo intentaré más tarde esta noche. Solo para ser claro, como sé que escribiste esto como una respuesta general, en mi caso específico los nodos serían lo que llamo divisiones, ¿correcto? –

+0

Sí. Nodo es un término común para un artículo en un árbol. – Tyrsius

+0

También muchas gracias por abordar la función de copia también. Iba a hacer eso luego de que derrotara la función de eliminación. ¡Gracias por ahorrarme un montón de tiempo y enseñarme un buen javascript nocaut! –

1

yo era capaz de crear una versión de trabajo de su código en el siguiente jsFiddle: http://jsfiddle.net/3eQNf/. Parecía que bajar a 2 temas principales:

  1. Tenías un problema de contexto con el uso de la palabra "this" en la clase de división. Agregar la variable auto resolvió ese problema.

  2. Necesitaba agregar una única división de nivel de raíz y vincularla a sus elementos secundarios. Esto hace que todas las recursiones funcionen como se esperaba. De esta forma también elimina la necesidad de que el método addDivision fuera de su tournamentViewModel

Además, digo, yo tenía que añadir los trozos para su distrito, región y clases pricingStructure desde los que no fueron incluidos en el código de ejemplo anterior. Espero que esto ayude.

+0

Gracias por dejarme saber lo que estaba mal. Pensé que había limpiado el código del distrito, región, etc. Oh bien. Sin embargo, me di cuenta de que no puedo copiar una división de nivel superior con el violín que me proporcionó, y la copia realmente solo crea cuadros de texto que apuntan a objetos ya existentes. Sé que mi pregunta no era sobre copiar, solo quería señalarlo. –

Cuestiones relacionadas