so i have a method called cetak() like this
var res = "";
Future<void> cetak(String query) async {
var req = await SqlConn.readData(query);
var parsedJson = jsonDecode(req);
setState(() {
res = parsedJson[0]['CUST_KELO'];
});
}
and im using cetak() method like this
cetak("SPS_SALEMISA_7 'MW','FB','11'")
the table in my database have so many column, and i want to display some of them, for example i want to display CUST_KELO column.
but when i want to display res in Text() widget, nothing is show, the code is
Text(res),
but in my debugConsole (im using VScode),
E/flutter ( 4539): ..."CUST_KELO":115, "CLXX_DEFA":1, "AREA_COMP":03, "WAXX_NMBR":6285852517258}]
and CUST_KELO value on debugconsole is same like in the database/
any idea how to display CUST_KELO Column in Text() widget
Check if setState() is called for the same widget that has text. Maybe you rebuild the parent but child is const Stateless widget.
Related
I have this Firebase structure:
Firebase Structure.
Then I have a function in my Code, which adds a map called "set".
My Structure is looking like this after: New structure.
Now i want an onUpdate Firebase function, which is called after the map "set" is added in any document.
This function should shuffle my "question" array.
I tried something like this:
exports.shuffleSet = functions.firestore
.document('duell/{duell_id}/set/questions')
.onUpdate((change, context) => {
const data = change.after.data();
const previousData = change.before.data();
if (data.name == previousData.name) {
return null;
}
//shuffle code here
});
But Im not sure if .document('duell/{duell_id}/set/questions') is the correct way to navigate to the question array. And at the beginning the "set" is not even existing as explained at the top.
How do I navigate to the question array correctly, that I can pull it & update it shuffled?
You should pass a document path to functions.firestore.document(). You cannot pass a field name, since Firestore Cloud Functions are triggered by documents events.
So you should do as follows:
exports.shuffleSet = functions.firestore
.document('duell/{duell_id}')
.onUpdate((change, context) => {
if (!change.after.data().shuffledSet) {
const data = change.after.data();
const question = data.set.question; // get the value of the question field
const shuffledSet = shuffle(question); // generate the new, suffled set. It’s up to you to write this function
return change.after.ref.update({shuffledSet});
} else {
return null; // Nothing to do, the shuffled field is already calculated
}
});
My query string is being generated correctly, but doesn't get added to the api unless I click the search button twice. After the initial first click, the search works fine each time. Unless I reload the page. Same is true if using a different input for the search.
As you can see in the console. The input data is defined in the search form.
First click..
SearchForm.js:26 IDXT001 2222
API.js:8 The query string is undefined
Second Click..
API.js:8 The query string is filter=IDXT001|2222
Is this a issue with timing? Seems stange that it works fine after each subsequent click.
Api..
search: function(query) {
console.log("The query string is " + query)
return axios.get("http://api/document?" + query );
},
Method..
loadContracts = (query) => {
API.search(query)
.then(res => {
const contracts = res.data;
this.setState({ contracts })
})
.catch(err => console.log(err));
};
Submit button..
handleFormSubmit = event => {
event.preventDefault();
const formData = this.state.formValues
let keys = Object.keys(formData);
keys.map(k => {
let query = '';
if (query !== "")
query += `&`;
query += `filter=`
query += `${k}|${formData[k]}`
this.setState({query}) ;
return this.loadContracts(this.state.query);
})
};
EDIT
Does not work fine each time after first click. If I change the data value after first click, the previous value get added to the api. So this is definitely a timing issue. My guess is that the query string is being added to the state after first click and then sent to the api on next click. So I need to change the code to have the query string be directly added to the loadcontracts function or have a .then before after sending to state and then return loadContracts()?
The problem was that I had the loadContracts = (query) method above the handleFormSubmit. So since react is top-down, the query string was stuck in the state on the first click and wasn't being added to the loadContracts = (query) until the second click. That's how I'm seeing it anyways. Correct me if I'm wrong.
I'm trying to render a message to a span tag specific to an item in a list. I've read a lot about React 'refs', but can't figure out how to populate the span with the message after it's been referenced.
So there's a list of items and each item row has their own button which triggers an API with the id associated with that item. Depending on the API response, i want to update the span tag with the response message, but only for that item
When the list is created the items are looped thru and each item includes this
<span ref={'msg' + data.id}></span><Button onClick={() => this.handleResend(data.id)}>Resend Email</Button>
After the API call, I want to reference the specific span and render the correct message inside of it. But I can't figure out how to render to the span at this point of the code. I know this doesn't work, but it's essentially what I am trying to do. Any ideas?
if (response.status === 200) {
this.refs['msg' + id] = "Email sent";
I recommand using state. because string refs legacy (https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs)
const msgs = [
{ id:1, send:false },
{ id:2, send:false },
{ id:3, send:false },
];
this.state = {
msgs
};
return this.state.msgs.map((msg, index) => {
const status = msg.send ? "Email Sent" : "";
<span>{ status }</span><Button onClick={() => this.handleResend(index)}>Resend Email</Button>
});
async handleResend (index) {
const response = await callAPI(...);
if(reponse.status !== 200) return;
const newMsgs = _.cloneDeep(this.state.msgs);
newMsgs[index].send = true;
this.setState({
msgs: newMsgs
})
}
The workaround is set innerText
this.refs['msg' + id].innerText = "Email sent";
But rather than using ref try to use state to update elements inside render.
i was facing with this issue right now and i figured it out this way:
// currentQuestion is a dynamic Object that comes from somewhere and type is a value
const _target = `${currentQuestion.type}_01`
const _val = this[`${_target}`].current.clientHeight // here is the magic
please note that we don't use . after this to call the ref and not using refs to achieve what we want.
i just guessed that this should be an Object that would hold inner variables of the current object. then since ref is inside of that object then we should be able to call it using dynamic values like above...
i can say that it worked automagically!
I am using protractor for e2e testing.
There is a ag-grid table where multiple columns are sorted in ascending order.
How do i go about verifying this?
Picture of Sample table
In AgGrid the rows might not always be displayed in the same order as you insert them from your data-model. But they always get assigned the attribute "row-index" correctly, so you can query for it to identify which rows are displayed at which index.
So in your E2E-tests, you should create two so-called "page objects" (a selector fo something in your view, separated from the text-execution code, google for page object pattern) like this:
// list page object
export class AgGridList {
constructor(private el: ElementFinder) {}
async getAllDisplayedRows(): Promise<AgGridRow[]> {
const rows = $('div.ag-body-container').$$('div.ag-row');
await browser.wait(EC.presenceOf(rows.get(0)), 5000);
const result = await rows.reduce((acc: AgGridRow[], elem) => [...acc, new AgGridArtikelRow(elem)], []);
return await this.sortedRows(result);
}
private async sortedRows(rows: AgGridRow[]): Promise<AgGridRow[]> {
const rowsWithRowsId = [];
for (const row of rows) {
const rowIndex = await row.getRowIndex();
rowsWithRowsId.push({rowIndex, row});
}
rowsWithRowsId.sort((e1, e2) => e1.rowIndex - e2.rowIndex);
return rowsWithRowsId.map(elem => elem.row);
}
}
// row page object
export class AgGridRow {
constructor(private el: ElementFinder) {}
async getRowIndex(): Promise<number> {
const rowIndexAsString: string = await this.el.getAttribute('row-index');
return parseInt(rowIndexAsString, 10);
}
}
And in your test:
it('should display rows in right order', async () => {
const rows = await gridList.getCurrentDisplayedRows(); // gridList is your AgGridList page object, initialised in beforeEach()
// now you can compare the displayed order to the order inside your data model
});
What this code does: you make page objects for accessing the table as a whole and for accessing elements within a row. To accessing the list in the same order as it is displayed in the view, you have to get all displayed rows (with lazy loading or pagination it should be below 100, otherwise your implementation is bad), get the rowIndex from each of them, sort by it and only then return the grid-list to the test-execution (.spec) file.
I'm using angular-ui-fullcalendar to show and edit events. Users can log in and have unique uid when logged in. I want to use this to distinguish events made by current user from other events. I want to give current user events another backgroundColor.
What is the best way to do this??
I tried several things. My data looks like this:
```
database
bookings
-KWnAYjnYEAeErpvGg0-
end: "2016-11-16T12:00:00"
start: "2016-11-16T10:00:00"
stick: true
title: "Brugernavn Her"
uid: "1f17fc37-2a28-4c24-8526-3882f59849e9"
```
I tried to filter all data with current user uid like this
var ref = firebase.database().ref().child("bookings");
var query = ref.orderByChild("uid").equalTo(currentAuth.uid);
var bookings = $firebaseArray(query);
$scope.eventSources = [bookings];
This doesn't return anything. If I omit the filter in line 2 it returns all bookings as expected. But even if the filter worked it would not solve my problem, because I want to fetch both current user events and all other events. Firebase does not have a "not equal to" filter option...
I tried to loop through each record and compare uids and setting backgroundColor if condition was met:
var ref = firebase.database().ref().child("bookings");
var bookings = $firebaseArray(ref);
bookings.$ref().on("value", function(snapshot) {
var list = snapshot.val();
for (var obj in list) {
if ( !list.hasOwnProperty(obj) ) continue;
var b = list[obj];
if (b.uid === currentAuth.uid) {
b.className = "myBooking";
b.backgroundColor = "red";
}
}
});
$scope.eventSources = [bookings];
But this causes asynchronous problems so the 'bookings' array assigned to $scope.eventSources wasn't modified. I tried to move the $scope.eventSources = [bookings] inside the async code block but FullCalendar apparently can't handle that and renders nothing.
I also tried this but no luck either:
bookings.$loaded()
.then(function(data) {
$scope.eventSources = [data];
})
.catch(function(error) {
console.log("Error:", error);
});
What is the best solution to my problem?
If you're looking to modify the data that is loaded/synchronized from Firebase, you should extend the $firebaseArray service. Doing this through $loaded() is wrong, since that will only trigger for initial data.
See the AngularFire documentation on Extending $firebaseArray and Kato's answer on Joining data between paths based on id using AngularFire for examples.