Flutter TextField autofocus not working with SlideTransition - animation

I have a screen with a single TextField (with autofocus: true) and a FlatButton. When I do not use SlideTransition the TextField properly gets focus when the screen is accessed. However, when I simply change the route to use SlideTransition for a nice animation to the second page, the TextField doesn't auto focus.
Example:
Autofocus works with:
Navigator.push(context, MaterialPageRoute(builder: (context) => SecondPage()),);
Autofocus does not work with (EnterExitRoute class from this article):
Navigator.push(context,EnterExitRoute(exitPage: FirstPage(), enterPage: SecondPage()));
How can I get the TextField to autofocus when using the animation to the SecondPage?

I finally got this working using FocusNode. I had tried FocusNode before posting. The difference that got it working was to not have these lines inside initState like examples show:
myFocusNode = FocusNode();
FocusScope.of(context).requestFocus(myFocusNode);
initState wasn't getting called. I am using StatefulWidget. I'm not sure why initState wasn't getting called. Maybe someone could provide a reason?

Related

Kendo ScrollView - Refresh/redraw current page

I'm using a Kendo ScrollView to display person images on a form.
Separate from the ScrollView, users can change the display order of the images. After they save their changes to the display order, the ScrollView is reloaded, scrolls to the first item, and should display the images in their new order.
However, I've noticed that when the ScrollView is currently on the first page, that page does not get refreshed/redrawn.
My ScrollView looks something like this:
#(Html.Kendo().ScrollView()
.Name("personImage")
.TemplateId("personImageTemplate")
.DataSource(d => d
.Custom()
.Type("aspnetmvc-ajax")
.Transport(t => t
.Read(r => r.Action("PersonImages_Read", "Person", new { personID = Model.ID } ))
)
.Schema(s => s.Data("Data").Total("Total"))
.ServerPaging(false)
.PageSize(1)
)
)
The template looks like this:
<script type="text/x-kendo-tmpl" id="personImageTemplate">
<img class="personImage"
src="#(Url.Action("ImageRender", "Person"))?imageID=#= data.ID #"
title="#= data.Filename #" />
</script>
And here is my refresh function:
function refreshPersonImageScrollView() {
var scrollView = $("#personImage").data("kendoScrollView");
if (scrollView) {
scrollView.dataSource.read();
// https://docs.telerik.com/kendo-ui/api/javascript/ui/scrollview/methods/refresh
// redraws, doesn't re-read from datasource
scrollView.refresh();
// scroll to first image
scrollView.scrollTo(0);
}
}
When I watch the requests being made when I call this function, I see this:
A. When a page other than the first page is selected:
PersonImages_Read (the ScrollView's dataSource read)
The ScrollView scrolls to the first image
3x ImageRender, as it renders the first 3 items in the ScrollView
B. When the first page is selected:
PersonImages_Read (the ScrollView's dataSource read)
Nothing else
I tried switching the order of scrollView.refresh() and scrollView.scrollTo(0), but the result does not change.
Is there any way to get Kendo to refresh/redraw the current page? I thought refresh would do it, based on the documentation, but it does not.
Edit
I've been able to replicate this issue in REPL. To see the behavior in action:
Note the "Rendered" time under the first image.
Scroll to the second image in the ScrollView.
Wait several seconds, then click the "Refresh" button.
The ScrollView should scroll back to the first image.
Observe that the "Rendered" time under the first image matches the "Last clicked" time reported below the "Refresh" button, and is no longer what it was in step #1. (This is the correct behavior.)
Remain on the first image for several seconds. Note the "Rendered" time listed before continuing.
Click the "Refresh" button.
Note that the "Last clicked" time has updated, and in the "Log" section, there is an entry that reads "dataSource read complete" at approx. the same time. However, the "Rendered" time under the image has not changed, and there is no log entry that says "image for product #X loaded".
I am using Kendo version 2021.3.1109 in my project. The Kendo version in the REPL above is 2022.3.913 and it still occurs in that version.
I have found a way to resolve the issue, but this may be worth opening a possible bug ticket with Telerik, because you would think that scrollView.refresh call would work.
What I changed in your refreshPersonImageScrollview function was to call setDataSource on the scrollview rather than calling the refresh method. Like so:
function refreshPersonImageScrollView() {
$("#refresh-last-clicked").text("Last clicked: " + getCurrentTime());
addToLog("refresh button clicked");
var scrollView = $("#personImage").data("kendoScrollView");
if (scrollView) {
scrollView.dataSource.read();
scrollView.setDataSource(scrollView.dataSource);
// scroll to first image
scrollView.scrollTo(0);
}
}
This appears to force the scrollView to re-evaluate its life choices and properly refresh :) However, it does seem to trigger additional dataSource reads, so it's not ideal.
One other thing I tried that didn't resolve the problem, but may be a good thing to change to anyway, would be to utilize the promise returned by the dataSource.read call. Meaning, do your scrollView setDataSource and scrollTo calls after the dataSource read promise is settled, like so:
scrollView.dataSource.read().then(function() {
scrollView.setDataSource(scrollView.dataSource);
// scroll to first image
scrollView.scrollTo(0);
});
REPL link here

Making focus works inside a CK Editor 5 createUIElement

So I've a custom widget which renders a custom component.
conversion.for('editingDowncast').elementToElement({
model: 'modelName',
view: (modelElement, viewWriter) => {
const modelName = modelElement.getAttribute('modelName');
const modelNameView = viewWriter.createContainerElement('span', {
class: 'modelName',
'data-modelName': modelName,
});
const reactWrapper = viewWriter.createUIElement(
'span',
{
class: 'modelName__react-wrapper',
},
function (this, domDocument) {
const domElement = this.toDomElement(domDocument);
rendermodelName(modelName, domElement);
return domElement;
},
);
viewWriter.insert(
viewWriter.createPositionAt(modelNameView, 0),
reactWrapper,
);
return toWidgetEditable(modelNameView, viewWriter);
},
});
Where rendermodelName will give back a React component with a simple input box as
return (
<div>
<input type="text" />
</div>
);
https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/react.html.
But the problem is, whenever I tried to add some content inside the input, the focus is lost from the field and automatically moved to the surrounding editor. What am I missing. Tried creating a focushandler and adding the modelNameView to it.
Should I go with the new createRawElement? My current CK5 is 20.0.0 So I don't want any breaking changes coming now.
EDIT:
I researched a little bit more. seems like createRawElement may not work here. I think this doesn't have a simple solution. I tried with allowContentOf: '$block' which also not letting me focus. But these values are explicitly for normal CK widget, not for a react component.
I had the same issue and solved it by adding this tag to the parent div that wraps my Vue component.
https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/ui/widget-internals.html#exclude-dom-events-from-default-handlers
Adding from CKE Docs:
Sometimes it can be useful to prevent processing of events by default handlers, for example using React component inside an UIElement in the widget where, by default, widget itself wants to control everything. To make it possible the only thing to do is to add a data-cke-ignore-events attribute to an element or to its ancestor and then all events triggered by any of children from that element will be ignored in default handlers.
Let’s see it in an short example:
<div data-cke-ignore-events="true">
<button>Click!</button>
</div>
In the above template events dispatched from the button, which is placed inside containing data-cke-ignore-events attribute, will be ignored by default event handlers.
I faced the similar issue.
CKEditor will takes all the events on React component which you hosted on Widget.
The work around is to stop propagation of events to CKEditor which are fired from your DOM element(domElement) where your React component hosted.
Here is the sample code:
https://github.com/ckeditor/ckeditor5-core/compare/proto/input-widget#diff-44ca1561ce575490eac0d660407d5144R239
You should stop all required events. Also you can't paste any content inside the input field of React component. That will also listened by clipboardInput event of CKEditor.

react-smooth-scrollbar programmatically change the scroll position?

I'm using this scroll bar from idiotWu which works great so far:
https://github.com/idiotWu/react-smooth-scrollbar
What I need to do next is in my react project, I need to programatically change the scroll position. In my project, when my fires reactComponent.render() again because of some things I'm doing, I need to scroll back to the top of the <Scrollbar />. I don't see in the documentation any mention of how to do something like a element.scrollTop() or <Scrollbar scrollPosition={0} />.
I tried to manually set the transform translate3d of <div class="scroll-content">, but that didn't work because the scrollbar is saving it's scroll position value somewhere, and I don't know how to access it.
How do I reset the scroll to the beginning? Alternatively, how do I state the scroll position?
EDIT
I also tried each of these but they all did not produce the results I wanted
export default class MyClass extends React.Component {
render() {
document.getElementById('panel').setPosition(0,0); // setPosition is not a defined method
document.getElementById('panel').scrollTop=0; // had no effect
scrollbar.setPosition(0,0); // scrollbar not defined
scrollbar.scrollTop=0; //scrollbar not defined
return (<Scrollbar id="panel">stuff</Scrollbar>);
}
}
Try scrollbar.scrollTop = 0 or scrollbar.setPosition(scrollbar.offset.x, 0).

Nativescript Android - hide keyboard

In my Nativescript app, the application starts with the login page. On iOS everything looks good, but on android, the username field is focused and the keyboard is showing. Is there a way to prevent this from happening?
So far I have tried:
Getting a reference of another element (a label) and calling lbl.focus() in the page's onLoaded event
getting a reference of the username textfield and calling txt.dismissSoftInput() and txt.android.clearFocus()
None of this worked. Is there another way to hide the keyboard when the page is loaded?
Thank you
I guess the username field is either textview or textfield. If so, try this on loaded callback:
var myTextview = page.getViewById("myTextView");
myTextView.dismissSoftInput();
So I ended up implementing a different solution. This may not be the best approach, but it serves its purpose in my case and I wanted to share it for those of you that face a similar scenario.
in page's loaded event I included this code:
if (page.android) {
var un = page.getViewById('username');
var p = page.getViewById('password');
un.android.setFocusable(false);
p.android.setFocusable(false);
setTimeout(function () {
un.android.setFocusableInTouchMode(true);
p.android.setFocusableInTouchMode(true);
}, 300);
}
The key here is the setTimeout function (Thanks Emil Oberg for pointing me to the right direction). As far as I understand, here is what is happening:
The page loads and we call setFocusable(false) on the only 2 text fields to prevent Android from setting the focus on them
Then we wait 300ms to allow Android to do its initialization
When the timeout executes, call setFocusableInTouchMode(true) to allow the fields to gain focus.
At this point the page is loaded without any fields to be in focus and with the keyboard hidden. If the user taps any of the fields the keyboard will appear and they can proceed to log in as usual.
As I mentioned, this may not be the best, or correct, approach, but works for me. Hope this can save someone the time to research the issue.
You want to clear the focus of the field in the loaded callback:
var searchBar = page.getViewById('my-search-bar-id');
if (searchBar.android) {
searchBar.android.clearFocus();
}
What about combining both tips above?
onClear(args) {
const searchBar = <SearchBar>args.object;
if (isAndroid && searchBar.android != undefined){//avoid random unpleasant error
setTimeout(() => { // the key here was this timeout
searchBar.android.clearFocus();
}, 1)
}
}

Scriptaculous Autocomplete list closes on scroll bar click

I have a really annoying issue with Autocomplete with Prototype 1.6. I set up and dialog-style div with a form, which contains an Autocomplete. Everything works fine until I click the scroll bar, or drag it; it closes the list of suggestions. I checked this solution but now I got an javascript error
event.srcElement is undefined
I was checking the controls.js and tried to catch the event object inside the onBlur event, but it travels empty. Printed the offsetX property and is undefined. Looks like the event doesn't exist anymore. either way, it prevents that the list closes but, If I click outside the area, the list now doesn't close. And that's kinda of issue too
Anyone with this same issue? Any idea?
Thanks in advance
I was having the exact issue yesterday, but after doing some r&d I got a pretty handy fix for this.
By default this script was hiding the result div (Suggestion List) on the blur event on the search text box so as soon as we click on result div's scroll bar focus gets lost from input element & result div closes. So I did a small edit in controls.js to change the behavior of script, so now result div close method doesn't invoke on blur (focus out) from input element but triggered on the click on the document except the text input element.
For your convenience I've put the edited controls.js here.
If you like to know what has changed in JS file, here it is;
Added a event listener to the document. Just below this line
"Event.observe(this.update, "keypress", this.onKeyPress.bindAsEventListener(this));"
Event.observe($(document), "mouseup", this.onMouseup.bindAsEventListener(this));
Added a new onMouseup method.
onMouseup: function(event) {
if(!this.hasFocus) {
this.hideTimeout = setTimeout(this.hide.bind(this), 250);
this.hasFocus = false;
this.active = false;
}
},
Modify the onBlur method (Comment out two line in block)
onBlur: function(event) {
//this.hideTimeout = setTimeout(this.hide.bind(this), 250);
//this.active = false;
this.hasFocus = false;
}
I hope this will solve your issue.
Thanks
Vinod Kumar

Resources