TypeError on split() - javascript

I am trying to hide elements based on whether the user has added the class numbers to the database which I am retrieving through json data. If all the class numbers are present on the component I want to hide it.
At the moment I keep getting this error:
TypeError: $(...).data(...).split is not a function
export function VisaToggleComponent() {
let json = {
visa_subclass:[462,500,801]
};
let elements = document.querySelectorAll('[data-visa-hide]');
console.log(elements);
$(elements).each(function() {
let data = json.visa_subclass,
target = $(this).data('visa-hide').split(',').map(Number);
console.log(target);
for (let i in data) {
let val = data[i];
let index = target.indexOf(val);
if(index > -1) {
$(this).hide();
}
}
});
}

split is a method of the String object. Since you're getting
TypeError: $(...).data(...).split is not a function
It means $(this).data('visa-hide') is not a string.
To be honest, I didnt try to understand your code, however if you think $(this).data('visa-hide') is string-like data type you have to change $(this).data('visa-hide').split(',') to String.prototype.split.call($(this).data('visa-hide'), ',')

Related

Trouble with Addition Assignment in Array from Firebase

I have a scenario where i need to query multiple collections at once and retrieve the values based on the collection name. I use Promise.all to do so and it works accordingly like so
var dbPromises = [];
dbPromises.push(
admin.firestore().collection("collection1").where("user_id", "==", uid).get(),
admin.firestore().collection("collection2").where("user_id", "==", uid).get(),
admin.firestore().collection("collection3").where("user_id", "==", uid).get(),
);
const promiseConst = await Promise.all(dbPromises);
promiseConst.forEach((qs) => {
if (qs.size > 0) {
if (qs.query._queryOptions.collectionId == "collection1") {
qs.docs.map((doc) => {
valuesArr1.push(doc.data().arr);
});
} else if (qs.query._queryOptions.collectionId == "Collection2") {
qs.docs.map((doc) => {
valuesArr2.push(doc.data());
});
} else if (qs.query._queryOptions.collectionId == "collection3") {
qs.docs.map((doc) => {
valuesArr3.push(doc.data());
});
}
} else {
return
}
});
for (var i=0; i < valuesArr1.length; i++) {
if (valuesArr1[i].desiredData) {
console.log('datas from for loop on datas array', valuesArr1[i].desiredData)
globalVariable += `<img src="${valuesArr1[i].desiredData}">`;
}
}
Once I do this I map the query snapshot I get and am able to retrieve the values up to this point like so
From the first collection I retrieve an array from a firestore document and then the following collections i just retrieve all documents from the collections. This all 'works' in that when I console.log into the functions console the data shows up exactly as expected. It's only when I want to iterate over the data and assign the results to a global variable to use elsewhere that strange behavior occurs.
The console.log shows the desired data in the functions console with no issues, but the output when I interpolate that data into the html and send it off in nodemailer I get the following result
undefined is always the first in the response when i use the += addition assignment operator, but if i just use the = assignment operator there's no undefined but I obviously don't get all the data I'm expecting.
There are no undefined values or documents in the collections that I'm retrieving, I've checked thoroughly and even deleted documents to make sure of it. After days of researching I've come to the conclusion it has to do with the asynchronous nature of the promise I'm working with and the data not being immediately ready when I iterate it.
Can someone help me understand what I'm doing wrong and how to fix it in node?
I figured out a solution to my problem and would like to share it in hopes it saves a future viewer some time.
Before, I was storing the results of the array from Firebase inside a global variable. To save some head scratching I'll post the code again below.
var globalVariableArray = []
var globalVariable
var dbPromises = [];
dbPromises.push(
admin.firestore().collection("DataCollection").where("user_id", "==", uid).get()
);
const promiseConst = await Promise.all(dbPromises);
promiseConst.forEach((qs) => {
if (qs.size > 0) {
if (qs.query._queryOptions.collectionId == "DataCollection") {
Promise.all(
qs.docs.map(doc => {
globalVariableArray = doc.data().arrayWithDesiredData;
})
);
}
else {
return
}
});
globalVariableArray.map(gv => {
globalVariable += `<p>gv.desiredData</p>` // <--- Right here is where the problem area was
})
var mailOptions = {
from: foo#blurdybloop.com,
to: 'bar#blurdybloop.com
subject: 'Almost but not quite',
html: `${globalVariable}`
};
The above code give the expected output, but the output would always have undefined first before the data showed. This happened no matter how the array from Firebase was iterated over.
After strengthening my Google-Fu, I worked out the following solution
var globalVariableArray = []
var globalVariable
var dbPromises = [];
dbPromises.push(
admin.firestore().collection("DataCollection").where("user_id", "==", uid).get()
);
const promiseConst = await Promise.all(dbPromises);
promiseConst.forEach((qs) => {
if (qs.size > 0) {
if (qs.query._queryOptions.collectionId == "DataCollection") {
Promise.all(
qs.docs.map(doc => {
globalVariableArray = doc.data().arrayWithDesiredData;
})
);
}
else {
return
}
});
var mailOptions = {
from: foo#blurdybloop.com,
to: 'bar#blurdybloop.com
subject: 'It works!!',
html: `${globalVariableArray.map(dataIWantedAllAlong => <p>dataIWantedAllAlong.desiredData</p> )}` <--- Here I simply loop through the array inside the interpolation blocks and voila! no more undefined showing up in the results
};
I perform the loop inside the brackets where I interpolate the dynamic data and am no longer getting that pesky undefined showing up in my emails.
Safe travels and happy coding to you all!

Firebase - Get field using variable as property

Im trying to get a field from a "doc.data" using a variable, the thing is that i want to reuse that function with different field names.
This is the code:
btnsEditvalue.forEach((btn) => {
btn.addEventListener("click", async (e) => {
try {
propToEdit = e.target.dataset.prop;
const doc = await getElement(e.target.dataset.id, col);
const element = doc.data();
console.log(element.propToEdit)
editElement.value = element.e.target.dataset.prop;
id = doc.id;
}
catch {
console.log("error");
}
});
});
The output is undefined, because "propToEdit" isnt a field in my database.
You can try passing the dynamic key using the bracket notation, instead of the dot notation.
Refer to javascript object property accessors.
const element = doc.data()
const ELEMENT_KEY: string = 'propToEdit'
console.log(element[ELEMENT_KEY])
You can access fields dynamically with a custom name
fieldName = "stringValue"
element[fieldName]
this does depend entirely on where doc from doc.data() is maintained
You can wrap it into a function as well, this will return the value or null.
You can swap null out with any other default value you want.
function getField(fieldName, doc){
return doc.data()[fieldName] || null;
}

React fixed-data-table: Uncaught TypeError: this._dataList.getSize is not a function

I'm attempting to use this example by the React developers to make a search filter for a table.
I have the table working fine with data from my backend statically. I have taken out an array for "sample" data to get the search functionality working. But I'm having a difficult time wrapping my head around how they use the "fake data" to populate their table as seen here, in contrary to "just" populating it with a test array as I want to.
Here's my source code. I want to filter through the "firstName" column, just as in Facebook's example(For simplicity). The error stems from when getSize() is called... But I suspect the issue is something else.
class DataListWrapper {
constructor(indexMap, data) {
this._indexMap = indexMap;
this._data = data;
}
getSize() {
return this._indexMap.length;
}
getObjectAt(index) {
return this._data.getObjectAt(
this._indexMap[index],
);
}
}
class NameTable extends React.Component {
constructor(props) {
super(props);
this.testDataArr = []; // An array.
this._dataList = this.testDataArr;
console.log(JSON.stringify(this._dataList)); // It prints the array correctly.
this.state = {
filteredDataList: new DataListWrapper([], this._dataList)
};
this._onFilterChange = this._onFilterChange.bind(this);
}
_onFilterChange(e) {
if (!e.target.value) {
this.setState({
filteredDataList: this._dataList,
});
}
var filterBy = e.target.value;
var size = this._dataList.getSize();
var filteredIndexes = [];
for (var index = 0; index < size; index++) {
var {firstName} = this._dataList.getObjectAt(index);
if (firstName.indexOf(filterBy) !== -1) {
filteredIndexes.push(index);
}
}
this.setState({
filteredDataList: new DataListWrapper(filteredIndexes, this._dataList),
});
}
render() {
var filteredDataList = this.state.filteredDataList;
if (!filteredDataList) {
return <div>Loading table.. </div>;
}
var rowsCount = filteredDataList.getSize();
return (
<div>
<input onChange={this._onFilterChange} type="text" placeholder='Search for first name.. ' />
{/*A table goes here, which renders fine normally without the search filter. */}
</div>
);
}
}
export default NameTable
Your problem is in _onFilterChange method.
You are doing this:
var size = this._dataList.getSize();
this._dataList is just an array, that's why getSize() does not exist in that object.
If I'm not misundertanding you should do this:
var size = this.state.filteredDataList.getSize();
The same will happend inside the loop, you are doing this:
var {firstName} = this._dataList.getObjectAt(index);
when you should do this:
var {firstName} = this.state.filteredDataList.getObjectAt(index);
Your _onFilterChange method should look something like this:
_onFilterChange(e) {
if (!e.target.value) {
this.setState({
filteredDataList: this._dataList,
});
}
var filterBy = e.target.value;
//var size = this._dataList.getSize();
var size = this.state.filteredDataList.getSize();
var filteredIndexes = [];
for (var index = 0; index < size; index++) {
//var {firstName} = this._dataList.getObjectAt(index);
var {firstName} = this.state.filteredDataList.getObjectAt(index);
if (firstName.indexOf(filterBy) !== -1) {
filteredIndexes.push(index);
}
}
this.setState({
filteredDataList: new DataListWrapper(filteredIndexes, this._dataList),
});
}
getSize() and getObjectAt() can only be called on a data object which implements these methods, such as the DataListWrapper object.
If you pass a plain data array to render() then it does not offer the getSize() and getElementAt() methods and the call to the methods will fail.
The original demo works because the FakeObjectDataListStore data is an object (a 'FakeObjectDataListStore') which implements the getSize and getObjectAt methods).
So easiest integration is to make sure the data passed in is an object that offer these methods. Based in my case on the 'examples/FilterExample' I found the easiest integration (after struggling with many bad ones) was to turn the existing 'helpers/FakeObjectDataListStore.js' into my own helpers/ObjectDataListStore.js (or chose your name) thus retaining the existing method wrapping structure and size params throughout the design. I then simply replaced the calls to the 'fake' component with references to my own non-wrapped local arrays of list rows. You can arrange your local data to be static, or dynamically loaded from whatever database environment you use. It was then easy to modify the _setFiltered() method to filter on something else than 'firstName'.
The cool thing with FixedDataTable is its ability to browse large lists,
and that the developer can write own custom cell renderers for example displaying a progress bar, button or menu anywhere in a list row.

Meteor: Underscore _findWhere iteration through loop objects only works in chrome console, in app it says undefined

I'm trying to fetch an object 'single Post' within an object 'Posts' from a json file within meteor, which looks like this.
I found an effective way of doing it, using underscore findWhere to get to it. this is the code
_.findWhere(_.findWhere(CategoryCollection.find().fetch(),
{"_id":"CategoryPublication-5"}).posts,{"ID":46});
however when i put this into meteor, i'm getting undefined
this is the code i used
Template.CategoryArticleSingle.helpers({
articles: function () {
var id = FlowRouter.getParam('ID')
var category = FlowRouter.getParam('category')
console.log(CategoryCollection.find().fetch());
let match = _.findWhere(_.findWhere(CategoryCollection.find().fetch(), {"_id":category}).posts,{"ID": id});
console.log("match",id,category,match);
return match;
}
});
Why am i getting undefined
update.
would this be correct? i substituted the 47 id, with just id so i can use it for any link.
Im getting "category" is read-only error.
Template.CategoryArticleSingle.helpers({
articles: function () {
var id = FlowRouter.getParam('ID')
var category = FlowRouter.getParam('category')
console.log(CategoryCollection.find().fetch());
const category = CategoryCollection.find().fetch().find(c => c._id === id);
let post = null;
if (category) {
post = category.posts.find(p => p.ID === id);
}
console.log("post",id,category,post);
return post;
}
});
There's no need to use lodash/underscore's findWhere. This functionality is built into ES2015. Also, you may consider breaking up the code into a few lines to make it more legible.
const category = CategoryCollection.find().fetch().find(c => c._id === 'CategoryPublication-5');
let post = null;
if (category) {
post = category.posts.find(p => p.ID === 47);
}

'undefined' elements in the array

I have the following JavaScript I am using to save selected check boxes:
function SubmitCheckBoxes()
{
alert("test");
var selectedIDs = [];
var x = 0;
a = document.getElementsByTagName("input");
for (i = 0; i < a.length; i++) {
if (a[i].type == "checkbox" ) {
if (a[i].checked) {
alert(a[i].value);
selectedIDs[x] = a[i].value;
x++;
}
}
}
$.post('./Courses/SaveAndRedirect', selectedIDs, function (data) { });
}
However when I look at the form data being submitted all its says is undefined: undefined for each element in the array.
Not sure what the problem is here.
It is the data attribute in the jquery post method that is wrong. It can't take an array as a parameter. Here is the documentation
data map or string that is sent to the server with the request.
Try using a object literal instead:
$.post('./Courses/SaveAndRedirect', {selectedIDs: selectedIDs}, function (data) { });
I would also try writing selectedIDs[x] = a[i].value; differently:
selectedIDs.push(a[i].value);
I think the problem may be that your post variables are associated with just a numeric instance rather than a field name
You can try something like this:
var selectedIDs = [];
$('input[type="checkbox"]:checked').forEach(function(i, e){
selectedIDs.push($(e).val());
});
$.post('./Courses/SaveAndRedirect', selectedIDs, function (data) { });

Categories

Resources