Fluid scroll List with paging - pagination

I have a JSON Model like this:
[
{code:'01', descr:'descr 01'},
{code:'02', descr:'descr 02'},
{code:'03', descr:'descr 03'},
{code:'04', descr:'descr 04'},
{code:'05', descr:'descr 05'},
{code:'06', descr:'descr 06'},
{code:'07', descr:'descr 07'},
{code:'08', descr:'descr 08'},
{code:'09', descr:'descr 09'},
{code:'10', descr:'descr 10'}
]
I show the array in a List https://sapui5.hana.ondemand.com/docs/api/symbols/sap.m.List.html
I use the list (in a Dialog, but this is not significant) to make the user choice the value to set in an Input field.
I don't use ODATA, but I use rest methods to retrieve the list. I use a server-side pagination to retrieve blocks of data; for example:
when I open the list I call
getHints, {from:1, to 10}
The server send back the list with first 10 record and I show rightly their in the list.
Then I scroll the list and when I am at the end the event updateFinished is run and I call the next 10 records:
getHints, {from:11, to 20}
and the server send back
[
{code:'11', descr:'descr 11'},
{code:'12', descr:'descr 12'},
{code:'13', descr:'descr 13'},
{code:'14', descr:'descr 14'},
{code:'15', descr:'descr 15'},
{code:'16', descr:'descr 16'},
{code:'17', descr:'descr 17'},
{code:'18', descr:'descr 18'},
{code:'19', descr:'descr 19'},
{code:'20', descr:'descr 20'}
]
In the callback I push the record in the JSONModel and I have now 20 records in the list BUT I have a strange behavior:
The scroll bar return to the top and in this mode the user does not have a fluid scroll.
How can I solve my strange problem?
PS.
I update my model in this mode:
var aElements=oModel.getProperty('/elements');
_.map(p_serverData.data.lookup, function (oElement) {
var oHintElement = {};
oHintElement.code = oElement.code;
oHintElement.description = oElement.descr;
aElements.push(oHintElement);
});
oModel.setProperty('/elements', aElements);

Related

react axios get request unable to pass/access response data

I am trying to create a dynamic list that depends on the amount of items from the backend; using axios get request, I am able to successfully get the data. However, when I try passing the data on to a function or printing the data, it doesn't print out the full data. It only shows the item tag (1, 0...) and when I tried accessing the data itself its giving me undefined.
await axios.get("backend.com/category")
.then((res) => {
var result = [];
//console.log(res.data) shows the array with the actual data
for (var resdata in res.data) {
//console.log(resdata) shows only 1 and 0
result.push(
<div>
<ItemCards data = {resdata}></ItemCards>
</div>
);
}
Here are the responses I've gotten:
when logging before mapping :
when logging inside mapping/ItemCards function:
Does anyone know how to fix this? Thank you very much for your time.
change your loop to this one if you want to pass your array data as props to child component:
for (var resdata of res.data) {
result.push(
<div>
<ItemCards data={resdata} />
</div>
);
}

Dash app auto update with dcc.Interval not working

I am trying to get my dash dashboard to auto update using Dcc.Interval and Callbacks. I can't figure out what I am doing wrong here. The html.P component "children" are not updating and it doesn't seem like the Interval is bein initiated:
app.layout = html.Div([
# Previous day column
dbc.Col([html.H1(PREV_DAY,
style={'textAlign': 'center', 'height': '5%', 'margin-top': '30px', 'margin-bottom': '25px',
'font-family': 'Consolas', 'font-size': 'xxx-large'}),
dbc.Card(
[
dbc.CardBody(
[
html.H4(id='card_title_1', children=['Sales'], className='card-title'),
html.P(id='card_text_1', children=['Sample text.']),
dcc.Interval(
id='interval-component',
interval=10 * 1000, # in milliseconds
n_intervals=0
)
], style={'textAlign': 'center', 'font-family': 'Consolas'}
)
], style={'margin-top': '15px', 'margin-bottom': '15px', 'height': '30%'}
),
I am trying to update the html.P(id='card_text_1') element with each interval. Here is my callbacks:
### SECTION - Callbacks ###
#app.callback(
Output('card_text_1', 'children'),
Input('interval-component', 'n_intervals'))
def update_metrics(n):
salesYest = 'test'
return [{}.format(salesYest)]
If you look at the console where you run the app you will see this error:
AttributeError: 'dict' object has no attribute 'format'
The problem is this part in your callback
return [{}.format(salesYest)]
As the error says a dictionary doesn't have an attribute format.
Now I'm not really sure what you're trying to do exactly in the callback, but the Interval component itself is working fine. You can test this by changing your callback to something like this:
#app.callback(
Output("card_text_1", "children"), Input("interval-component", "n_intervals")
)
def update_metrics(n):
return n
Also keep in mind that you have set the interval to 10000 milliseconds. So be sure to check if 10 seconds have actually passed in case it still seems it isn't doing anything or lower the interval when debugging.
Also aside from the format issue you're currently returning the same value every time so you wouldn't notice anything either way.

Why does ga:clientId dimension request return empty array when using python3 google analytics v4?

Trying to get clientId from google analytics currently via python code:
def get_report(analytics):
return analytics.reports().batchGet(
body={
"reportRequests": [
{
"viewId": VIEW_ID,
"dateRanges": [{"startDate": "7daysAgo", "endDate": "today"}],
"dimensions": [{"name": "ga:pagePath"}, {"name": "ga:clientId"}],
"metrics": [{"expression": "ga:pageViews"}, {"expression": "ga:sessions"},
{"expression": "ga:avgTimeOnPage"}]
}]
}
).execute()
this code returns empty array, if I remove:
{"name": "ga:clientId"}
It works fine, and returns all the data. Also using Java, I can get the clientID number fine in such fashion:
Dimension clientId = new Dimension().setName("ga:clientId");
ReportRequest request = new ReportRequest()
.setViewId(VIEW_ID)
.setDateRanges(Arrays.asList(dateRange))
.setMetrics(lstMetrics)
.setDimensions(lstDim);
ArrayList<ReportRequest> requests = new ArrayList<ReportRequest>();
requests.add(request);
// Create the GetReportsRequest object.
GetReportsRequest getReport = new GetReportsRequest()
.setReportRequests(requests);
// Call the batchGet method.
GetReportsResponse response = service.reports().batchGet(getReport).execute();
// Return the response.
return response;
But python fails to produce same data response.

Using puppeteer how do you get all child nodes of a node?

I'm having trouble finding a way to iterate subnodes of a given node in puppeteer. I do not know the html structure beforehand, just the id of the parent element.
var elemId = "myelemid";
const doc = await page._client.send('DOM.getDocument');
const node = await page._client.send('DOM.querySelector', {
nodeId: doc.root.nodeId,
selector: '#' + elemId
});
//node.children empty
//node['object'].children empty
//try requesting childnodes
var id = node.nodeId;
var childNodes = await page._client.send('DOM.requestChildNodes', {
nodeId: id
});
//childNodes empty
//try requesting by resolveNode?
var aNode = await page._client.send('DOM.resolveNode', {
nodeId: id
});
//aNode.children is empty
Is there a way to get the children of a node if you don't know the html structure in puppeteer?
What I would do here is to use the evaluate method of Puppeteer to return the children elements of your node to your script as follows:
const nodeChildren = await page.$eval(cssSelector, (uiElement) => {
return uiElement.children;
});
console.log(nodeChildren); // Outputs the array of the nodes children
Hope this helps!
I ended up using page.evaluate to run some js that adds unique classnames to every element and subelement I want analyzed and then pass that back as JSON string since page.evaluate only returns a string. Then I just call DOM.querySelector on each of those unique selectors and loop through them that way.
Returning children from page.$eval doesn't give me protocol nodes that I can run more dev protocol functions on, and xpath doesn't solve my real problem because it can't recursively loop through all sub-children, then the sub-children of those children.
I'm closing the issue since labeling using unique classnames solves my problem.

sorting values of a hash object in ngRepeat - angularJS

I have an object like this:
$scope.phones = new Object();
$scope.phones['id1'] = {
"name":"Phone Name1",
"dateReleased":"2012-1-09 15:48:24"
};
$scope.phones['id2'] = {
"name": "Phone Name2",
"dateReleased":"2012-3-12 15:32:11"
};
$scope.phones['id3'] = {
"name": "Phone Name3",
"dateReleased":"2012-2-10 13:53:32"
};
I'm displaying this using ngRepeat. I'm not able to order by dateReleased. Also, ordering in reverse isn't working. My ngRepeat looks this:
<li ng-repeat="phone in phones | orderBy:dateReleased:true">
<p>{{phone.name}}</p>
<p>{{phone.dateReleased}}</p>
</li>
While ngRepeat can iterate a hash object, like $scope.phones in your example, the built-in orderBy filter will not work. I believe this is due to the way objects are stored. As other's have noted, you need to convert the hash to an array. While you can do this using the methods suggested above, I prefer to do it using a custom filter. This gives me the benefit of not having to alter my hash directly, and also let's me reuse the filter with other hashes.
yourApp.filter('orderObjectBy', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item) {
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
});
This filter converts the object into a standard array and sorts it by the field you specify. You can use the orderObjectBy filter exactly like orderBy, including a boolean value after the field name to specify whether the order should be reversed. In other words, false is ascending, true is descending.
<li ng-repeat="phone in phones | orderObjectBy:'dateReleased':true">
<p>{{phone.name}}</p>
<p>{{phone.dateReleased}}</p>
</li>
I've got a post on my blog regarding this topic.
If you check the documentation it says that the expression in orderBy can be a function, a string or an Array. An therefore you need dateReleased to be a string: 'dateReleased'
Also you need your phones Object be an actual Array.
Try:
$scope.phones = [{
"name":"Phone Name1",
"dateReleased":"2012-1-09 15:48:24"
},{
"name": "Phone Name2",
"dateReleased":"2012-3-12 15:32:11"
},{
"name": "Phone Name3",
"dateReleased":"2012-2-10 13:53:32"
}];
<li ng-repeat="phone in phones | orderBy:'dateReleased':true">
<p>{{phone.name}}</p>
<p>{{phone.dateReleased}}</p>
</li>
Both of the other answers get you part way there, but not all the way...
You'll need to create a function on your scope that converts the object to an array like so:
$scope.phonesArray = function() {
var result = [];
angular.forEach($scope.phones, function(phone, id) {
result.push(phone);
});
return result;
};
Then you'd call that instead of your object in your ngRepeat:
<li ng-repeat="phone in phonesArray() | orderBy:'dateReleased':true">
<p>{{phone.name}}</p>
<p>{{phone.dateReleased}}</p>
</li>
Also: Notice that 'dateReleased' is a string, so it knows to $eval that string off of the current item, otherwise it will check the parent $scope.dateReleased, which doesn't exist.
Here is a plunk for what I think you're trying to do
EDIT: You can also "convert" the object to an array and store it on the $scope, if you're worried about the function to do so being too "expensive", but that shouldn't be an issue, as you're developing a clientside app for one user, and not a server application for many users, meaning you have a little wiggle room for "expensive". (Which it won't be anyway)
First of all, you need to understand that ng:filter and ng:orderBy work with Arrays (an ordered collection of items), but you're trying to use them on Object (_un_ordered collection of items). One possible approach is to collect all the objects into an array, then proceed with ng-repeat on it instead. Like this:
<ul ng-init="phones = [
{name:'Phone Name 1', dateReleased:'2011-1-09 15:48:24'}
, {name:'Phone Name 2', dateReleased:'2012-3-12 15:32:11'}
, {name:'Phone Name 3', dateReleased:'2012-2-10 13:53:32'}];
pred = '-dateReleased';" >
<li ng-repeat="phone in phones | orderBy:pred">
<p>{{phone.name}}</p>
<p>{{phone.dateReleased}}</p>
</li>
</ul>

Resources