How to create dynamic callback for generated component - plotly-dash

I am able to understand how the callbacks work in the dash-table-experiment where the DataTable is part of the app.layout = Div/Html layout.
But how do I create the callback when the DataTable is generated like this and it is not part of the static layout?
def generate_table(tdf, max_rows=200):
return dt.DataTable(rows=tdf.to_dict('records'),
columns=tdf.columns,
row_selectable=True,
filterable=False,
sortable=False,
selected_row_indices=[],
id="datatable-gapminder"
)
If I say
#app.callback(
Output('datatable-gapminder', 'selected_row_indices'),
[Input('graph-gapminder', 'clickData')],
[State('datatable-gapminder', 'selected_row_indices')])
def update_selected_row_indices(clickData, selected_row_indices):
if clickData:
for point in clickData['points']:
if point['pointNumber'] in selected_row_indices:
selected_row_indices.remove(point['pointNumber'])
else:
selected_row_indices.append(point['pointNumber'])
return selected_row_indices
I get an error
Attempting to assign a callback to the
component with the id "datatable-gapminder" but no
components with id "datatable-gapminder" exist in the
app's layout.

You are getting that error because the component with id datatable-gapminder is not yet in the layout.
If you want to create callbacks for a component which is not yet in the layout, you have to suppress the callbacks exceptions.
app.config.supress_callback_exceptions = True
I think you will also need a function to serve the layout. By default, Dash apps store the app.layout in memory. If you set app.layout to a function, then you can serve a dynamic layout on every page load. See here.
def serve_layout():
layout = html.Div(
children=[
# dt.DataTable()
],
)
return layout
app.layout = serve_layout

I don't know, if that is currently at all possible with dash. However you might consider creating an empty data table component, and simply updating all it's properties in your call-back (except the id of course :)). If users are not supposed to see the empty data table on startup, you can set it as a hidden div in the beginning, and make sure it becomes visible in the callback.
If you decide to try this approach, make sure you return meaningful values each time the callback for creating the data table is called. Even if these values are empty.

Related

Forcing a Classified Document to Another Layout within Hyperscience

I want to force a document to classify against a particular layout on Hyperscience - is this possible? I can use the uuid, layout_uuid, layout_version_uuid, along with other metadata. I also want to include the pages belonging to the document if it has been classified already.
I’ve already set up the custom code block to perform this function as below:
def force_classification(submission: Any) -> Any:
***insert code here***
return submission
cct_force_classification = CodeBlock(
reference_name='force_classification',
code=force_classification,
code_input={'submission': previous_block.output('submission')},
title='Force Classification',
description='Force Classification',
)
Reading the SDK docs, I didn't see a clear way to do this. I'm wondering if this is just not possible?
Yes, this is possible! However, there are some limitations. You are able to use a custom code block to specify the layout that a document must be classified against if it has already been classified, as long as the layout that you’re forcing classification against is a semi-structured layout.
new_documents = []
for document in submission.get('documents', []):
if document['layout_uuid'] == 'layout_uuid[1]':
new_document = {
'uuid': document['id'],
'layout_version_uuid': 'layout_version_uuid[2]',
'layout_uuid': 'layout_uuid[1]',
'pages': [{
'submission_page_id': page['id'],
'page_number': page['submission_page_number'],
'classification_type': page['classification_type'],
} for page in document.get('pages', [])],
'metadata': {},
}
new_documents.append(new_document)
return {'submission': submission, 'new_documents': new_documents}
Note that, here, layout_uuid[1] refers to an existing document, and 2 corresponds to the metadata of the other layout you want to force classification against.
Keep in mind that this is still superficial (client side) and will not reflect in the Hyperscience db until you sync this new document back.

Angular changeDetectorRef.detectChanges() is making the page jump/scroll to the top

I have a function that takes in a list of objects that are used to for display in the view. It looks like this:
myFunction(objects: myObjects[]){
this.objects = objects;
this.changeDetectorRef.detectChanges();
}
This function is called in a subscription callback. eg:
this.myService.ReplaySubject.subscribe(_ => this.myFunction(_));
And the value of the replay subject is set on a polling interval in the service, so the data can be refreshed automatically and consumed in other components.
In the template I have a loop for the items in the list… eg:
<div class=“wrapper” *ngFor=“let object of this.objects; let i=index”>
The content is changing as expected, but the issue is that the page is scrolling/jumping to the top of the page each time I call changeDetectorRef.detectChanges() in myFunction(). I have tried calling changeDetectorRef.detach() in my component constructor and the method itself to see if that would maintain the scroll position, but I had no luck. I am sort of stumped for what else to try. Any ideas?

Android ListView binding programmatically

There are many examples of doing this in axml, but I would like to have a complete binding using code behind. To be honest, I would like to have NO axml, but seems like creating all the controls programmatically is a nightmare.
I first tried the suggestions at:
MvxListView create binding for template layout from code
I have my list binding from code-behind, and I get six rows (so source binding is working); but the cells itself does not bind.
Then at the following url:
Odd issue with MvvmCross, MvxListViewItem on Android
Stuart has the following comment: Have looked through. In this case, I don't think you want to use DelayBind. DelayBind is used to delay the binding action until next time the DataContext is set. In Android's MvxAdapter/MvxListItemView case, the DataContext is passed in the ctor - so DataContext isn't set again until the cell is reused. (This is different to iOS MvxTableDataSource).
So in essence, the only example I see shows DelayBind, which shouldn't work.
Can someone please show me some examples... thanks in advance.
Added reply to Comments:
Cheesebaron, first of all, a huge thank you and respect for all your contributions;
Now, why not use axml? Well, as programmers, we all have our own preferences and way of doing stuff - I guess I am old school where we didn't have any gui designer (not really true).
Real reasons:
Common Style: I have a setup where Core has all the style details, including what all the colors would be. My idea is, each platform would get the style details from core and update accordingly. It's easy for me to create controls with the correct style this way.
Copy-Paste across platform (which then I can even have as linked files if I wanted). For example, I have a login screen with web-like verification, where a red error text appears under a control; overall on that screen I have around 10 items that needs binding. I have already got iOS version working - so starting on Droid, I copied the whole binding section from ios, and it worked perfectly. So, the whole binding, I can make it same across all platform... Any possible error in my way will stop at building, which I think is a major advantage over axml binding. Even the control creation is extremely similar, where I have helpers with same method name.
Ofcourse I understand all the additional layout that has to be handled; to be honest, it's not that bad if one really think it through; I have created a StackPanel for Droid which is based on WP - that internally handles all the layouts for child views; so for LinearLayout, all I do is setup some custom parameters, and let my panel deal with it. Relative is a different story; so far, I have only one screen that's relative, and I can even make it Linear to reduce my additional layout code.
So, from my humble point of view, for my style, code-behind creation allows me to completely copy all my bindings (I do have some custom binding factories to allow that), copy all my control create lines; then only adding those controls to the view is the only part that is different (then again, droid and WP are almost identical). So there is no way I can miss something on one platform and all are forced to be the same. It also allows me to change all the styles for every platform just by changing the core. Finally, any binding error is detected during compile - and I love that.
My original question wasn't about NOT using axml... it was on how to use MvxListView where all the binding is done in code-behind; as I have explained, I got the list binding, but not the item/cell binding working.
Thanks again in advance.
Here is part of my LoginScreen from droid; I think it's acceptable amount of code for being without axml file.
//======================================================================================================
// create and add all controls
//======================================================================================================
var usernameEntry = ControlHelper.GetUITextFieldCustom(this, "Username.", maxLength: 20);
var usernameError = AddErrorLabel<UserAuthorization, string>(vm => ViewModel.Authorization.Username);
var passwordEntry = ControlHelper.GetUITextFieldCustom(this, "Password.", maxLength: 40, secureTextEntry: true);
var passwordError = AddErrorLabel<UserAuthorization, string>(vm => ViewModel.Authorization.Password);
var loginButton = ControlHelper.GetUIButtonMain(this);
var rememberMe = new UISwitch(this);
var joinLink = ControlHelper.GetUIButtonHyperLink(this, textAlignment: UITextAlignment.Center);
var copyRightText = ControlHelper.GetUILabel(this, textAlignment: UITextAlignment.Center);
var copyRightSite = ControlHelper.GetUIButtonHyperLink(this, textAlignment: UITextAlignment.Center);
var layout = new StackPanel(this, Orientation.Vertical)
{
Spacing = 15,
SubViews = new View[]
{
ControlHelper.GetUIImageView(this, Resource.Drawable.logo),
usernameEntry,
usernameError,
passwordEntry,
passwordError,
loginButton,
rememberMe,
joinLink,
ControlHelper.GetSpacer(this, ViewGroup.LayoutParams.MatchParent, weight: 2),
copyRightText,
copyRightSite
}
};
I just came across a similar situation myself using Mvx4.
The first link you mentioned had it almost correct AND when you combine it from Staurts comment in the second link and just remove the surrounding DelayBind call, everything should work out ok -
public class CustomListItemView
: MvxListItemView
{
public MvxListItemView(Context context,
IMvxLayoutInflater layoutInflater,
object dataContext,
int templateId)
: base(context, layoutInflater, dataContext, templateId)
{
var control = this.FindViewById<TextView>(Resource.Id.list_complex_title);
var set = this.CreateBindingSet<CustomListViewItem, YourThing>();
set.Bind(control).To(vm => vm.Title);
set.Apply();
}
}
p.s. I have asked for an Edit to the original link to help others.

Custom Register form not working

Hie folks..... When I click on submit button of the CUSTOM REGISTRATION form..... it redirects to the same page...... ?? No idea what this is about......
Controller: default.py
def register():
form=auth.register()
form.add_button('Cancel', URL('register'))
return dict(form=form)
View: register.html
Please take the little pain to open this link to view the html file.... I am unable to post the exact html code in here... problem with syntax..
http://pastebin.com/bPQu2DX3
print form.errors -> Storage {}
print form.accepts(request.vars,session) -> false
You have duplicated line form=auth.register()
You return dict(late=late, form=form) but late is never used in your controller...
I think you should simplify your controller :
def register():
form=auth.register()
form.add_button('Cancel', URL('register'))
return dict(form=form)
First, your first two lines are useless, as the third line simply overwrites the "form" variable with a completely new object. Second, auth.register() already handles the form processing, so you cannot subsequently call form.accepts(). If you want to control the flash messages, use the auth.messages object to set them.
Thanx folks .. Finally got the answer....
I was not putting all the fields in custom form..
the fields that one doesn't require and is validated as not null also needs to be mentioned in custom form as hidden attributes otherwise whole of the form won't get accepted.

How to use a QGraphicsWebView?

I want to use a QGraphicWebView inside a delegate to render a QTableView cell, but I just don't know what to do with the QStyleOptionGraphicsItem parameter the paint() method requires. How to build it up / where should I retrieve it?
I'm using this code as reference, so the paint() method should be something like this:
def paint(self, painter, option, index):
web = QGraphicsWebView()
web.setHtml(some_html_text)
web.page().viewportSize().setWidth(option.rect.width())
painter.save()
painter.translate(option.rect.topLeft());
painter.setClipRect(option.rect.translated(-option.rect.topLeft()))
web.paint(painter, ??????) # what here?
painter.restore()
Any advice?
I'll assume that you don't really need QGraphicsWebView and that QWebView is sufficient.
It's important to keep in mind that you're not expected to call QWidget::paintEvent() yourself. Given that constraint, you'll want to use a helper class that can render on a paint device or render using a given painter. QWebFrame has one such method in the form of its render function. Based off of your linked-to example, the following should work:
class HTMLDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
model = index.model()
record = model.listdata[index.row()]
# don't instantiate every time, so move this out
# to the class level
web = QWebView()
web.setHtml(record)
web.page().viewportSize().setWidth(option.rect.width())
painter.save()
painter.translate(option.rect.topLeft());
painter.setClipRect(option.rect.translated(-option.rect.topLeft()))
web.page().mainFrame().render(painter)
painter.restore()