Estoy analizando una cadena xml y la muestro como un árbol en d3.js. Puedo construir todo el árbol en el paso 'ingresar', pero ahora quiero hacerlo interactivo y extraer la configuración en un paso de actualización. Estoy siguiendo https://stackoverflow.com/a/24912466 para implementar el patrón de actualización general, pero parece que no puedo establecer el atributo en el elemento g fuera del paso de entrada:
const svg = d3.select("#canvas"); const xmlAsText = ` <root attrib1="foo" att2="foO"> <child1 attrib1="ba">zwei</child1> <child2>eins</child2> </root>`; treeDataXml = (new DOMParser()).parseFromString(xmlAsText, "text/xml"); let hierarchy = d3.hierarchy(treeDataXml.children[0], d => d.children); nodesData = d3.tree()(hierarchy); var myGroups = svg.selectAll("g").data(nodesData.descendants()); myGroupsEnter = myGroups.enter().append("g") // 1) works //myGroupsEnter .attr("class", "x"); // 2) doesn't work myGroups.select("g").attr("class", "x"); console.log(document.getElementById("canvas").childNodes[0].attributes[0]) alert(document.getElementById("canvas") .childNodes[0].attributes.length) <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg id="canvas"></svg> <body> <svg id="canvas"> <g class="x"></g> <g class="x"></g> <g class="x"></g> </svg> </body>pero con 2) es solo:
<body> <svg id="canvas"> <g></g> <g></g> <g></g> </svg> </body> Esperaría que con myGroups.select("g").attr("class", "x") los <g> s enter previamente se seleccionarán y tendrán su class de atributo establecida en "x". ¿Por qué no funciona esto? ¿Cómo puedo arreglar esto?
Las selecciones son inmutables, myGroups es una selección vacía: aún no contiene ningún elemento DOM. Como esta selección es la selección de actualización, esto tiene sentido, no hay nada que actualizar.
La selección myGroupsEnter contiene los elementos recién creados. La introducción de elementos no modifica myGroups , sigue siendo una selección vacía. Esto explica por qué myGroupsEnter.attr("class", "x"); funciona y myGroups.select("g").attr("class", "x"); no es.
D3 v3 y versiones anteriores agregaron elementos recién ingresados en la selección de actualización, por lo que algunos ejemplos pueden ser engañosos, pero como este comportamiento no era explícito, se eliminó
A menudo, desea combinar los elementos ingresados y actualizados en una selección, puede usar:
let combined = myGroups.merge(myGroupsEnter);De esta manera, independientemente de si está ingresando todos los elementos, actualizando todos los elementos o ingresando algunos y actualizando otros, puede modificar todos los elementos que existen (que no están cerrados).