D3 append is not a function when using with VueJS and Vuex - javascript

I have a html 'div' and I am trying to append another div to it by the following :
var myDiv = d3.select("#container")
myDiv.append("div")
And I get the following error :
myDiv .append is not a function
Any ideas ? I am using Vuex, so I instantiated the variable in the store and trying to set it to the d3 select.
I have put together a codepen that's similar to what I have : https://codepen.io/anon/pen/oMBGmd?editors=1010
const store = new Vuex.Store({
state: {
networkVariables: {
node: "",
data: [1, 2, 3, 4, 5]
},
container: ""
},
getters: {},
mutations: {}
});
console.log("line 33");
console.log(store);
var networkVariables = store.state.networkVariables;
var container = store.state.container;
container = d3.select("#container");
console.log(networkVariables);
networkVariables.node = container
.selectAll(".node")
.data(networkVariables.data);
console.log(networkVariables.node);
networkVariables.nodeEnter = networkVariables.node.append("div");

In your latest codepen, the error you mentioned is coming from the last line, where you are trying to append to the networkVariable.node directly -- without using the enter selection.
It seems to work for me when I change the last line to be:
networkVariables.nodeEnter = networkVariables.node.enter();
networkVariables.nodeEnter.append("div");

Here networkVariables.nodeEnter = networkVariables.node.append("div");, there is no append() in networkVariables.node object. I tried replacing networkVariables.node.append() with networkVariables.node[0].parentNode.append("div"), this seems to work in the snippet. can you try with this change.

The line in the codepen with the error is like #SteveR noticed the last line.
It is not the result of a d3.select() but a d3.selectAll(..).data(...). The array contains 5 empty placeholders and two fields. These are enter and exit, both functions. To convert this to a "selection" result you have to call one of these functions first before you can append().
But in the original question there should be no problem appending if the tag with the given id exists.
The codepen is not similar to the original question/example.

Related

"object HTMLDivElement" with outerHTML and with replaceWith() does nothing

I'm confused as to why this is failing.
I'm trying to directly replace a DIV completely with replaceWith from jquery.
i've tried bunch of variation, but either nothing gets updated. or if i try outerhtml [object HTMLDivElement] instead of the html. (which means I'm for sure working with a node, right? which means replaceWith() should work?).
I'm iterating through an array of currently displayed 'cardObjects', and comparing it to an identically structured incoming array (it's a sorted ordered list). the object's.html is the node element. and the object's.target is pointing to the element's id.
function cardConstructor(item)
{
var cardDiv = constructElement('div', "queCard", "machine"+item.machineID+"ID"+item.ID, "");
//more html stuff gets appended to this element, but not relevant for problem
cardObject =
{
ID: item.ID,
machineID: item.machineID,
lastID: item.lastID,
nextID: item.nextID,
jobID: item.jobID,
target: cardDiv.id, //string
html: cardDiv //node
}
return cardObject;
}
// here is where the problem is -
//it is in an update loop,
//this is failing
else if(inc[y].ID != current[y].ID)
{
console.log("ids do not match, splicing and replacing");
console.log("current y target is:");
console.log(current[y].target); //334 ---console output
var updateTarget = document.getElementById(current[y].target);
console.log("old html"); //337
console.log(updateTarget); //338
console.log("new html"); //339
console.log(inc[y].html); //340
updateTarget.replaceWith(inc[y].html);
console.log("update target updated: as"); //343
console.log(updateTarget); //344
current.splice(y,1, inc[y]);
}
the console.log output is:
current y target is:
machinewindow.php:334 machine1ID775
machinewindow.php:337 old html
machinewindow.php:338 <div class=​"queCard" id=​"machine1ID775">​<div class=​"queCardTitle" id=​"Titlemachine1ID775">​<div class=​"itter" id=​"itterDiv+1machine1ID775">​1​</div>​<button class=​"completeBtn" id=​"complete775" value=​"775">​complete​</button>​</div>​<div class=​"queCardBody" id=​"Bodymachine1ID775">​…​</div>​<div class=​"queCardFooterW" id=​"queCardFooterWmachine1ID775">​…​</div>​</div>​
machinewindow.php:339 new html
machinewindow.php:340 <div class=​"queCard" id=​"machine1ID774">​<div class=​"queCardTitle" id=​"Titlemachine1ID774">​…​</div>​<div class=​"queCardBody" id=​"Bodymachine1ID774">​…​</div>​<div class=​"queCardFooterW" id=​"queCardFooterWmachine1ID774">​…​</div>​</div>​
machinewindow.php:343 update target updated: as
machinewindow.php:344 <div class=​"queCard" id=​"machine1ID775">​<div class=​"queCardTitle" id=​"Titlemachine1ID775">​…​</div>​<div class=​"queCardBody" id=​"Bodymachine1ID775">​…​</div>​<div class=​"queCardFooterW" id=​"queCardFooterWmachine1ID775">​…​</div>​</div>​
here as shown in the console.log we get no updated div.
if i instead try updateTarget.outerHTML = inc[y].html - then I get [object HTMLDivElement] on the browser window.
I've tried a few iterations - and I'm a bit lost as to why this isn't working.
the object.html is a node, but won't replace another node with replaceWith();
I'm probably missing something.
also below is that constructElement function by request.
function constructElement(element, styleClass, type, data)
{
var ele = document.createElement(element);
ele.setAttribute("class", styleClass);
ele.setAttribute("id", type);
ele.innerHTML = data;
return ele;
}
If you want to use updateTarget.replaceWith(inc[y].html);
replace your line 335 with:
var updateTarget = $(current[y].target);
as replaceWith is a jQuery method and should be applied to jQuery object.
If you prefer using outerHTML, make sure you have a HTML string (not a node) on the right side, e.g.:
updateTarget.outerHTML = "<div>blah blah</div>";
or in your case:
updateTarget.outerHTML = inc[y].html.outerHTML;
Hope it helps.

How made a deep copy that can resolve a problem with a table

Im using the table material-table, where the set a new element to my object, called tableData. So that feature create an issues to my code and API because I update using Patch. I implemented a conventional and also custom deep copy of my object to avoid the table add this element to my object.
But for some reason it isnt working. This is an example of the table where you can see how it added the tableData to the example object. https://codesandbox.io/s/lx2v9pn91m Please check the console
Above I showed the real object, and in the element 5 array, appear the tableData after each render. Extra comment, the property of the table I passed to table is: data={MyRealObject.element5}
This is the struct of my real object:
MyRealObject{
element1: boolean,
element2: boolean ,
element3: Array ,
element4: Array ,
Cards: Array ,
}
Card{
Id: number ,
CardNumber : number ,
CardFormat : {CardFormatObject},
//here where appear the tableData after each render
}
CardFormatObject{
Id: number ,
CardNumberLength : number ,
CardFormatLength : number ,
Default:boolean ,
Name: string ,
}
This is the lastest custom deep copy I did and didnt work:
deepcopy(MyRealObject:MyRealObject):MyRealObject{
let salvaCard=[]
for(let i=0;i<user.Cards.length;i++){
salvaCard[i]=this.deepCardCopy(MyRealObject.Cards[i])
}
return{
element1: MyRealObject.element1,
element2: MyRealObject.element2,
element3: [...MyRealObject.element3], //I know here is not deep but isnt important now, and it isnt affected
element4: [...MyRealObject.element4],
Cards: salvaCard,
}as MyRealObject
}
public deepCardCopy(card:Card):Card{
return {
Id:card.Id,
CardNumber:card.CardNumber,
CardFormat:{...card.CardFormat}
} as Card;
}
//////////////////////////////
This are others deep code that I used and dont works, I share to save you time:
--------old solution 1(i dont like it, you can lose element if there are null)------------------------------------------------
// Cards: JSON.parse(JSON.stringify(MyRealObject.Cards)),
---------old solution 2-------------------------------------------
// MyRealObject.Cards.map(card=>{
// const {tableData,...record}=card
// return record
// }),
setState is an async function. That means you won't see the result right after calling it. You have to wait for setState to be finished. There is a callback-Parameter in setState which you can use to get the result of this.state
handleSelectedID = rowData => {
const selectedID = rowData.map(item => item.id);
this.setState({ selectedID }, () => {
// setState is async
// this is the callback
console.log(this.state.selectedID);
});
};
I changed your example-code a bit to give you an example of it: https://codesandbox.io/s/1olz33pmlj
I found a solutions, it is passsing the clone in the moment i passed the object to the table, for example:
data={MyRealObject.map(x => Object.assign({}, x))}
The issues was, that the people that create the table didnt make a clone to the data, the use the same reference, so it will be better do this to avoid problems that some one in the component didnt clone the object.
Kindly, noted, DONT used this way
data={...MyRealObject} or data={Object.assign({}, MyRealObject)}
The CORRECT is:
data={MyRealObject.map(x => Object.assign({}, x))}
Both expression look similiar but it isnot the same.

How to remove any firebase data using JavaScript?

I am building a web application using JavaScript and firebase.
everytime I click on the "remove" paragraph tag, I can only remove the most recent added item, but cannot remove the rest.
Example: if I have 9 items, and I just added a 10th item, I can only remove the 10th item, but not the other 9 items. I basically can only remove items in a backwards order, as opposed to being able to remove items in any order of my choice.
Here is my code:
function displayFav(){
const dbRef = firebase.database().ref();
dbRef.on("value", (firebaseData) => {
// empty out element before adding new updated firebase data so there are no repeated data
document.getElementById("displayUsername").innerHTML = "";
let accounts = [];
const accountData = firebaseData.val();
for (let itemKey in accountData) {
accountData[itemKey].key = itemKey;
accounts.push(accountData[itemKey])
const key = accountData[itemKey]["key"];
const password = accountData[itemKey]["password"];
let user = accountData[itemKey]["username"];
// code where I try to render results from page
document.getElementById('displayUsername').innerHTML += `
<li> Username: ${user} Password: ${password}</li>
<p id=${key}>Remove</p>
`;
// code where I try to remove the item
document.getElementById(key).addEventListener("click", function(){
removeItem(key)
})
}
});
}
This is my function to remove the firebase data:
function removeItem(itemToRemove){
const dbRef = firebase.database().ref(`${itemToRemove}`);
dbRef.remove();
};
What can I change or add to my code that will allow me to remove items in any order I want, instead of letting me delete only the most recent items?
Not trying to be rude, this is just a tip: Please indent/format your code well so that people can understand it without having to format it themselves. Usually when people see large code that's not well formatted, it throws them off (sometimes including me), and therefore they wouldn't want to continue to read or help you with the question.
Suppose you have a table called posts, and the structure looks like this:
that is:
{
<postId>: {
date: 1518925839059,
message: 'some message'
},
<postId>: {
date: 151892583967,
message: 'some message'
},
...
...
}
Suppose you want to delete the extra property of the first post, as circled in the picture, you must know the full path of the data:
firebase.database().ref('posts/-L5b1EZ1L_FycluzTIn8/extra').remove();
If you want to delete everything in post 1:
firebase.database().ref('posts/-L5b1EZ1L_FycluzTIn8').remove();
Or, if you want to delete every single post:
firebase.database().ref('posts').remove();

JavaScript variable remains undefined

I am struggling with my webpage. The JavaScript isn't doing what it should because a variable[] isn't being populated! Please consider my code:
var datasets = { "DataItem1": {
label: "Idle Count",
dataSeries: [[13, 75.72],[13, 1],[13, 0.17],[13, 55.72],[13, 90.72],[13, 91.06]],
Threshold_0: [[134, 1],[133, 1]],
Threshold_2: [[133, 1],[131, 1]]
}
};
var data = [];
var failedData = [];
data.push(datasets['DataItem1']['dataSeries']);
failedData.push(datasets['DataItem1']['Threshold_0']['Threshold_2']);
});
The issue is with
failedData.push(datasets['DataItem1']['Threshold_0']['Threshold_2']);
Using firebug's watch window, I can see that failedData is undefined when I add a break at this point. So, I hover the mouse over the array items on this line, and Threshold_0 has data, but Threshold_2 does not (Threshold_2 is undefined).
In the watch window, I can see that datasets[] has created all the objects as expected.
I can't see why and I'm very stuck.
Here you are trying to access the property Threshold_2 through Threshold_0, you should get it through DataItem1
failedData.push(datasets['DataItem1']['Threshold_0']['Threshold_2']);
Becomes
failedData.push(datasets['DataItem1']['Threshold_2']);
The following properties do have a value:
datasets['DataItem1']['Threshold_0'][0] == [134, 1]
datasets['DataItem1']['Threshold_0'][1] == [133, 1]
I'm not sure what you actually want to do. Maybe this is what you intend to do?
failedData.push(datasets['DataItem1']['Threshold_0']);
failedData.push(datasets['DataItem1']['Threshold_2']);
Otherwise, please describe what value(s) you want to end up in failedData.
You have a typo at the end. Remove the last });

removing element from mootools sortable

I'm trying to remove an item from a mootools sortable list, then serialize and save the new list.
I'd like to use a little bit of eye-candy rather than a straight destroy() on the element. I've built a fiddle here: http://jsfiddle.net/kBAqJ/4/
Note the order1 and order2 vars. This holds the serialized element before and after removing the item. If you use the destroy method to get rid of the element after removing it from the sortable, you get the right value for order2, eg. 4.
If you use nix(true) instead of destroy, you get 5 as the value of order1 and order2, even though the docs say that nix(true) calls destroy after dissolve.
Is this a bug in Mootools, or am I missing something? Is there a different way to add a dissolve effect while still using destroy that will get the right result?
window.addEvent('domready', function(){
var mySort = new Sortables('#example2 UL', {
clone: true,
revert: true,
opacity: 0.7
});
console.log (mySort.elements.length);
var order1 = mySort.serialize(0);
console.dir(order1);
mySort.removeItems($('item1')).destroy(); // this results in the correct value in the order2 var below
//mySort.removeItems($('item1')).nix({duration: 1000}, true); // this results in the wrong value for order2
console.log (mySort.elements.length);
var order2 = mySort.serialize(0);
console.dir(order2);
});
i don't think you'll find any effect or way which will destroy the element and still show it on the page ;) So it is not a moo tools bug
The serialize function is using the children of the list (ie. the <li> blocks) to make the array.
I would say the easiest way would be to get rid of their reference in the serialized array:
window.addEvent('domready', function(){
var mySort = new Sortables('#example2 UL', {
clone: true,
revert: true,
opacity: 0.7
});
console.log (mySort.elements.length);
var order1 = mySort.serialize(0);
console.dir(order1);
//mySort.removeItems($('item1')).destroy(); // this results in the correct value in the order2 var below
mySort.removeItems($('item1')).nix({duration: 1000}, true); // this results in the wrong value for order2
console.log (mySort.elements.length);
var order2 = mySort.serialize(0).erase("item1"); // we have to erase the item because he may still be in the list of children at this time…
console.dir(order2);
});
Cheers

Categories

Resources