Implement CSV download using current filters and sort - csv

I need to implement a download feature. It will read the data in the react-data-grid (adazzle), respecting the current columns, filters and sort, and create an array json (or comma separated strings) I can then pass to the react-csv module.
I have a data structure populated from the backend but it is not filtered nor sorted. I need to be able to ask the grid for it's data on a row-by-row basis. Can anyone point me in the right direction?

Without code or some context, I can't answer with certainty...
You supply the rowGetter prop with the collection to display, or the method to get the rows to display...I'm thinking if you filtering, then most likely you've got some sort of mechanism supporting that... Either way, you can use this property's value somehow to get exactly what you see in the grid.
If you literally want to interrogate the grid, you could try adding a reference to the grid, and then see if you can ask it for the row data. I can't remember with certainty that I saw a rows prop in the grids available props via the ref, but I imagine you should be able to (**,)
...
handleExport = async => {
const exportRows = rows;
// const exportRows = getRows(initialRows, filters);
// const exportRows = this.state.gridref.CurrentRows DISCLAIMER:CurrentRows is just for giving the idea... check out the ref yourself to see if it's possible to get the rows via the grid refs props.
downloadCSV( exportRows )
}
...
<ReactDataGrid
ref={input => {this.state.gridref = input}}
columns={columns}
rowGetter={i => rows[i]} // or maybe rowGetter={i => getRows(initialRows, filters)[i]}
rowsCount={rows.length}
onGridSort={(sortColumn, sortDirection) =>
setRows(sortRows(initialRows, sortColumn, sortDirection))
}
/>
I've only ever [set / initialised] the this.state.gridRef prop in my constructor, but I guess you could also [set / initialise] it in your componentDidMount as well...
initialise like this:
this.state.gridRef = React.createRef()

Related

How to render nested routes with multiple optional params and path placeholders?

I've been trying to use react-router to define a series of nested components/routes w/ optional params, but also separated by path placeholders.
i.e.
/list
/list/1
/list/items
/list/1/items
/list/1/items/1
I would assume the two <Route> paths would be something like:
/list/:listId?
and
`${match.url}`/items/:itemId?`
But alas.. "items" always ends up being accepted as the listId param, and therefore, the sub-routing for /items never matches.
I have a generic example I've coded here (doesn't accomplish a solution): https://stackblitz.com/edit/nesting-w-optional-params-react-router
I see examples all over the internet for /root/:id1?/:id2? but nothing for what I'm trying to do where I have a placeholder between the params: /root/:id1/placeholder/:id2.
Is this possible to do w/ react-router v4+ ??
Figured out a solution utilizing RR's children pattern, to always render the nested route/component, but then inside the component use path-to-regexp directly to do route matching and to grab relevant route params from props.location.pathname.
Relevant bit of code:
render() {
const pathRe = new PathToRegexp('/foo/:fooId?/bar/:barId?')
const match = pathRe.match(this.props.location.pathname)
if (!match) {
return null
}
const barId = (this.props.match && this.props.match.params.barId) || match.barId
return <h1>Bar <em>{barId}</em></h1>
}
https://stackblitz.com/edit/nesting-w-optional-params-react-router-solution

Updating Data within a unique randomly generated ID/KEY in firebase using HTML

function updateFirebase(){
const fb=firebase.database().ref()
//get field values
author = document.getElementById('uname').value
user_email = document.getElementById('umail').value
data = {author, user_email}
//update database
fb.child('Article/').update(data);
}
</script>
I have problem with my code. I want to update the data inside a table named "Article". Article has generated items with a unique key/id and each key has its own content. Lets say I want to be able to edit the "author" or change the "title", the problem is they each have a randomly generated key/id that I cant access. for example that "-LS39kReBHrKGqNj7h_". I can only save the data inside the "Article" tree but I cant change the "author" or the "title". How do i get a workaround this so I can change those properties?
Here is how my firebase looks like
It depends whether you have the record reference on the frontend before update or not (whether you have fetched it before you are trying to update it).
But generally, you have two options
You can store the key reference as an "id" field on the object.
To achieve that, you need two step process when creating the record at the first place
// Creates a new record in DB and returns it to you. Now you can get the "key"
const newRecord = firebase.database().ref('TABLE_NAME_REF').push();
newRecord.set({
id: newRecord.key
...
});
This is great if you fetch the list of records on the frontend and then you want to update one of them. Then you can just build the ref path like this
fb.child('Article/' + record.id ).update(data); // where record is the prefetched thing
You need to find the element based on its fields first. And once you have it, you can update it right away.
To achieve this, you can simply do something like:
firebase.database()
.ref('TABLE_NAME_REF') // let's say 'Article'
.orderByChild('RECORD_KEY') // Let's say 'author'
.equalTo('KEY_VALUE') // let's say 'zoranm'
.limitToFirst(1)
.once("value")
.then(res => {
// You need to loop, it always returns an array
res.forEach(record => {
console.log(record.key); // Here you get access to the "key"
fb.child('Article/' + record.key ).update(data); // This is your code pasted here
})
})

How can I get access to multiple values of nested JSON object?

I try to access to my data json file:
[{"id":1,"name":"Maria","project":[{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}]}
This is my approach:
data[0].name;
But like this I get only the result:
Animals
But I would need the result:
Animals, Cats
You are accessing only the name property of 0th index of project array.
To access all object at a time you need to loop over the array.
You can use Array.map for this.
var data = [{"id":1,"name":"Maria","project":[{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}]}]
var out = data[0].project.map(project => project.name).toString()
console.log(out)
If that's your actual data object, then data[0].name would give you "Maria". If I'm reading this right, though, you want to get all the names from the project array. You can use Array.map to do it fairly easily. Note the use of an ES6 arrow function to quickly and easily take in the object and return its name.
var bigObject = [{"id":1,"name":"Maria","project":[{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}]}];
var smallObject = [{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}];
console.log("Getting the names from the full array/data structure: "+bigObject[0].project.map(obj => obj.name))
console.log("Getting the names from just the project array: "+smallObject.map(obj => obj.name))
EDIT: As per your comment on the other answer, you said you needed to use the solution in this function:
"render": function (data, type, row) {if(Array.isArray(data)){return data.name;}}
To achieve this, it looks like you should use my bottom solution of the first snippet like so:
var data = [{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}];
function render(data, type, row){
if(Array.isArray(data)){
return data.map(obj => obj.name);
}
};
console.log("Render returns \""+render(data)+"\" as an array.");

Vuejs changes order of json_encoded array, when decodes it back from props in vuejs component

Php:
$json_string = "{
"26":{"blabla":123,"group_id":1,"from":"27.08.2018","to":"02.09.2018"},
"25":{"blabla":124,"group_id":1,"from":"20.08.2018","to":"26.08.2018"},
"24":{"blabla":125,"group_id":1,"from":"20.08.2018","to":"26.08.2018"}
}"
my.blade.php template:
<my-component :records={{ $json_string }}></my-component>
MyComponent.vue:
export default {
props: ['records'],
...
mounted: function () {
console.log(this.records);
}
Output is:
{__ob__: Observer}
24:(...)
25:(...)
26:(...)
And when I use v-for, records in my table in wrong order (like in console.log output).
What I am doing wrong?
EDIT:
I figured out 1 thing:
When I do json_encode on collection where indexes are from 0 till x, than json string is: [{some data}, {some data}]
But if I do ->get()->keyBy('id') (laravel) and than json_encode, json string is:
{ "26":{some data}, "25":{some data}, "24":{some data} }
Then how I understood, issue is in different outer brackets.
In Javascript keys of objects have no order. If you need a specific order then use arrays.
Here is documentation for keyBy Laravel method: https://laravel.com/docs/5.6/collections#method-keyby
I wanted to have ids for rows data to fast and easy access without iterating over all rows and check if there is somewhere key Id which is equals with my particular Id.
Solution: not to use keyBy method in Laravel and pass json string to Vue component like following [{some data}, {some data}] (as I described in my Question Edit section) - this will remain array order as it used to be.
I found this short and elegant way how to do this, instead of writing js function by myself:
Its find() method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
Example:
let row = records.find( record => record.id === idToFind );

Filtering and rearranging model/content in Ember Controllers

Let's say I have a JSON array of data, something like:
[ {"name":"parijat","age":28},
{"name":"paul","age":28},
{"name":"steven","age"27},
...
]
that is part of my model, and this model is setup like this:
App.UserRoute = Ember.Route.extend({
model:function(){
return App.User.FIXTURES ; // defined above
}
});
I want to get the unique ages from this JSON array and display them in my template, so I reference the computed properties article and read up a little on how to enumerate Ember Enumerables, to eventually get this:
App.UserController = Ember.ArrayController.extend({
ages:function(){
var data = this.get('content');
var ages = data.filter(function(item){
return item.age;
});
}.property('content');
});
Now the above piece of code for controller is not correct but the problem is that it doesn't even go into data.filter() method if I add a console.log statements inside. IMO, it should typically be console logging as many times as there exist a App.Users.FIXTURE. I tried using property('content.#each') which did not work either. Nor did changing this.get('content') to this.get('content.#each') or this.get('content.#each').toArray() {spat an error}.
Not sure what to do here or what I am completely missing.
Filter is used for reducing the number of items, not for mapping.
You can use data.mapBy('age') to get an array of your ages:
ages:function(){
return this.get('content').mapBy('age');
}.property('content.#each')
or in your handlebars function you can just use the each helper:
{{#each item in controller}}
{{item.age}}
{{/each}}