Pulling data from API into react-bootstrap-table-2 - reactjs

I'm pulling in data from an API and trying to display it on my bootstrap table. It displays but I'm getting some errors. The first issue is in regard to 'data' being required.
The second issue seems to be the data hasn't loaded in time but I've used an if statement to load the data first.
if (this.props.dataState.loaded){
data = this.props.data.content;
} else {
this.renderLoading();
}
return( ...
Sometimes it displays the page without issues, other times it effects the other components and they won't load. I always get the console errors.
Any idea what I'm doing wrong?
Thanks!

You need to check the existence of dataState too, the same way you are checking for dataState.loaded. For the below code, I am assuming the default Props type for data.content is an array.
Try this:
if (this.props.dataState && this.props.dataState.loaded){
data = this.props.data.content ? this.props.data.content : [] ;
} else {
this.renderLoading();
}
I hope this will work.

Related

DocumentSnapshot.exists returns false when Document exists

I am using React Native and Firebase Firestore. Below is my code where the error persists. It should display true, as the document does exist inside of the firestore, however it keeps returning false. I tried testing it with a value that I manually created on the Firestore website and the .exists property was true. When I create a document with .set however, it returns false. Anyone have an explanation or a solution as to why this could be happening? I have referred to other StackOverflow articles but they were not helpful as this does not seem to be happening to anyone else. Let me know if more info is needed. Thanks in advance.
export default class GuestSession extends Component {
state = {
isLoading: true,
users: [],
code: 0
}
constructor(props) {
super(props);
let displayName = firebase.auth().currentUser.displayName
this.state.code = props.route.params.code
const docRef = firebase.firestore().collection('sessions').doc(this.state.code)
docRef.get().then((docSnapshot) => {
if(docSnapshot.exists) {
console.log("exists")
} else {
console.log("doesn't exist")
}
})
this.state.isLoading = false
}
}
I have figured out my issue. When dynamically creating documents on the go, you want to make sure that you are creating a single document first, instead of a document that includes a collection with another document. For example,
//dynamic document creation of 2 separate documents
firebase.firestore().collection('sessions').doc(this.state.code)
.collection('users').doc('exampleUserDocument').set({username: username})
should instead be written as
const sessionRef = firebase.firestore().collection('sessions')
sessionRef.doc(this.state.code).set({exampleField: value})
//properly sets session document
sessionRef.doc(this.state.code).collection('users').doc('exampleUserDocument').set({username: username})
//properly sets user document
This allows for the document to be properly created, with all property values of a document to be set for both a session document, and for a user document. I feel like when you do the longer version stated first, it skips over properly creating a document and setting proper values in the session collection to save some loading time for the system. This is more of a hypothesis on what happens rather than a factual statement, but that is my assumption. I hope this helps others in the future.

Problems with parsing a JSON Array after retrieving from firebase when using ionic-selectable

I'm currently developing an App using Ionic 3 and Firebase. I'm using ionic-selectable (you can see my stackblitz here) for the user to select an option from my firebase database array and return the selected option to the user's id.
I have got everything to work, except that ionic-selectable is not reading the retrieved array form firebase.
I'm retrieving the array using the following code:
this.itemsRefdiag = afg.list('medicalhx');
this.items = this.itemsRefdiag.snapshotChanges().map(changes => {
return changes.map(c => ({ ...c.payload.val() }));
});
const dgRef = this.afg.database.ref();
dgRef.child('medicalhx').orderByChild('name').on('value', snapshot => { this.snapshot2 = JSON.stringify(snapshot).replace(/"[0-9]":{"name":|{|}/g, ""); })
My console.log results in:
"Hyperthyroidism","Hypothyroidism","Diabetes Type 1","Diabetes Type 2"
However, when using ionic-selectable for private diagnoses: Diagnosis[] = [this.snapshot2], I get 'undefined' options. However, when I manually type in private diagnoses: Diagnosis[] = ["Hyperthyroidism","Hypothyroidism","Diabetes Type 1","Diabetes Type 2"], it works. I also tried parsing the JSON array using the following code instead:
this.itemsRefdiag = afg.list('medicalhx');
this.items = this.itemsRefdiag.snapshotChanges().map(changes => {
return changes.map(c => ({ ...c.payload.val() }));
});
const dbRef = this.afg.database.ref();
dbRef.child('medicalhx').orderByChild('name').on('value', snapshot =>
{ let snapshot3 = JSON.stringify(snapshot).replace(/"}/g, `"`);
let snapshot4 = snapshot3.replace(/"[0-9]":{"name":|{|}|"/g, "");
this.snapshot2 = snapshot4.split(",");
});
My console.log results in an Object with separate strings (an array):
["Hyperthyroidism","Hypothyroidism","Diabetes Type 1","Diabetes Type 2"]
However, ionic-selectable still doesn't seem to read that and I get undefined error. Any ideas on what I may be doing wrong with the array?
EDIT
It actually does work the second time around, however the console error pops up the first time and I believe this is because it's not waiting for the array results to pop-up the first time around. Is there a way to add a wait time until the array loads?
The second code listed in the question converting it to a real array worked but required a loading time, hence poping up a console error. I managed to get around the loading time issue by implementing Asynchronous searching as per this stackblitz.

Mongo query returns empty array on initial run

I have a collection named People that holds multiple documents. I am using Meteor JS for my website. When I run People.find({status: "Pending"}) it initially returns an empty array. If I wrap it in a Tracker.autorun:
Tracker.autorun(function(){
var peeps = People.find({status: "Pending"})
Session.set('listo', peeps)
console.log(peeps)
})
It finds the documents after first returning an empty array.
// => []
// => [{}]
The issue is that the first value (the empty array) is getting passed to my template and it is displaying none of the documents. I am using react for rendering:
render() {
return (
{
Session.get('listo').map((item) => {
HTML HERE
})
)
}
I thought that a session variable would work for this case but maybe this is conflicting with react or something, I'm not really sure.
To clarify the problem, the data always eventually gets loaded into the the listo session variable but this new data is not displayed in the render() function.

TypeError: push is not a function

Here is my code for factories.html
af.factory("PurchaseFactory",function(){
var productlist={products:[]};
return{
getpurchaseCart:function(){
return productlist;
},
addPurchaseCart:function(products){
productlist.products.push(products);
}
}
})
For Services.html
as.service("PurchaseService",function(PurchaseFactory){
this.getAllPurchase=function(){
return PurchaseFactory.getpurchaseCart();
}
this.addPurchase=function(products)
{
PurchaseFactory.addPurchaseCart(products);
}
})
For Controller.html
ac.controller("PurchaseController",function($scope,PurchaseService){
$scope.savepurchase=function(products){
if($scope.products._id==undefined){
$scope.products=angular.extend($scope.products,$scope.sizes)
PurchaseService.addPurchase($scope.products);
}
}
}
Here i have an another function in the same controller, as
$scope.saveorder=function(cartorder){
$scope.Mainpurchaselist=angular.extend($scope.cartorder,$scope.getpurchaseList)
CartService.addPurchaseCart($scope.Mainpurchaselist);
$scope.getpurchaseList.products={}
$scope.cartorder={}
$scope.products={}
$rootScope.isLogin=false;
CartService.deletecartyPurchase(idx);
Notification.success({message: 'your Cart Saving Successfully', delay: 1000});
}
In my HTML file, i have a button with function as savepurchase(products).
For first time its saving data but from second time its showing me error as TypeError:productlist.products.push is not a function. If I refresh the page its again saving the data, but continuously its not working.Let me know where the code goes wrong.
Here $scope.getpurchaselist.products={} is used to make a data null for every new purchase. If I remove the $scope.getpurchaselist.products={}, its working fine with no error but the problem is that the list is not getting null.
SO finally i have two ways
1. either to make it null by writing $scope.getpurchaselist.products={} but error as productlist.products.push is not a function let me know to overcome that error
2. Or to remove that line and let me know, how to make it null
I think, $scope.getpurchaseList.products={} is effecting you. As it passing an empty object instead of array as soon as the controller load. So, try removing it.
The condition if($scope.products._id==undefined) is breaking you. please check the logic you wrote. keep in mind $scope.products and products both are different variable in savepurchase function.
After extending $scope.products first time, condition return false.
change the $scope.products into just products. because u pass the products as paramater to the savepurchase() function. so no need to define as scope.products in ur controller

Difference in accessing variables in views

I've two controllers one is "Upload" which deals with images uploads and other is "Page" whid deals with the creation of pages of CMS now if in my "Upload" controller I load both the models i.e 'image_m' which deals with image upload and "page_m" which deals with the pages creation I've highlighted the relevant code my problem is if I access the variables in the view
$this->data['images'] = $this->image_m->get(); sent by this I can access in foreach loop as "$images->image_title, $images->image_path" etc
But the variable sent by this line ***$this->data['get_with_images'] = $this->page_m->get_no_parents();*** as $get_with_images->page_name, $get_with_images->page_id etc produces given error
A PHP Error was encountered
Severity: Notice
Message: Trying to get property of non-object
Filename: upload/index.php
Line Number: 20
what is the difference between these two access levels one for $image & other for $get_with_images because I can only access its values as $get_with_images
class Upload extends Admin_Controller {
public function __construct() {
parent::__construct();
***$this->load->model('image_m');
$this->load->model('page_m');***
}
public function index($id = NULL) {
//var_dump($this->data['images'] = $this->image_m->get_with_images());
//$this->data['images'] = $this->image_m->get_with_images();
***$this->data['images'] = $this->image_m->get();***
$this->data['subview'] = 'admin/upload/index';
if ($id) {
$this->data['image'] = $this->image_m->get($id);
count($this->data['image']) || $this->data['errors'][] = 'Page Could not be found';
}
$id == NULL || $this->data['image'] = $this->image_m->get($id);
/*this calls the page_m model function to load all the pages from pages table*/
***$this->data['get_with_images'] = $this->page_m->get_no_parents();***
You are not posting all your code so its hard to tell but is it because you used $this-> in the controller, but you haven't done the same thing in the view?
In this case i would recommend not using $this-> because its not necessary. Also its much better to check for errors etc when you call the model so do something like
if ( ! $data['images'] = $this->image_m->get($id) ) {
// Failure -- show an appropriate view for not getting any images
// am showing $data in case you have other values that are getting passed
$this->load->view( 'sadview', $data ); }
else {
// Success -- show a view to display images
$this->load->view( 'awesomeview', $data ); }
so we are saying if nothing came back - the ! is a negative - then show the failure view. Else $data['images'] came back, and it will be passed to the view. note i have not had to use $this-> for anything and it won't be needed in the view.
Would also suggest using separate methods - have one method to show all images and a separate method like returnimage($id) to show an image based on a specific validated $id.
====== Edit
You can access as many models as you want and pass that data to the View. You have a different issue - the problem is that you are waiting until the View to find out - and then it makes it more difficult to figure out what is wrong.
Look at this page and make sure you understand the differences between query results
http://ellislab.com/codeigniter/user-guide/database/results.html
When you have problems like this the first thing to do is make a simple view, and echo out directly from the model method that is giving you problems. Its probably something very simple but you are having to look through so much code that its difficult to discover.
The next thing is that for every method you write, you need to ask yourself 'what if it doesn't return anything?' and then deal with those conditions as part of your code. Always validate any input coming in to your methods (even links) and always have fallbacks for any method connecting to a database.
On your view do a var_dump($get_with_images) The error being given is that you are trying to use/access $get_with_images as an object but it is not an object.
or better yet on your controller do a
echo '<pre>';
var_dump($this->page_m->get_no_parents());
exit();
maybe your model is not returning anything or is returning something but the data is not an object , maybe an array of object that you still need to loop through in some cases.

Resources