The new Material UI DatePicker has a renderInput prop that gets a function that renders a text field. Works well enough, except that this function is rendered twice, and on first render it only receives some of the props it needs.
When rendered with React Testing Library, only the first render happens. Notably, the endAdornment is not present. So it's impossible to getByRole('button') and click the button to open the picker modal.
I've tried various permutations of waitFor() and rerender() but can't seem to get the button to show up.
Here's a code sandbox that shows the two versions of the renderInput params being logged out. (I've also got a test in there to look for the button, but unfortunately I'm also doing something wrong with the test and it's not running.)
Any suggestions?
It is because Mui’s DatePicker render mobile view by default.
Below would fix it:
beforeEach(() => {
// add window.matchMedia
// this is necessary for the date picker to be rendered in desktop mode.
// if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: (query: string): MediaQueryList => ({
media: query,
// this is the media query that #material-ui/pickers uses to determine if a device is a desktop device
matches: query === '(pointer: fine)',
onchange: () => {},
addEventListener: () => {},
removeEventListener: () => {},
addListener: () => {},
removeListener: () => {},
dispatchEvent: () => false,
}),
});
});
afterEach(() => {
delete window.matchMedia;
});
For more details: github issue
Related
I have a button, and when I press it, a certain card gets deleted after API call. I have to re-route the user back to the same page so that he sees that the card is deleted. The code works just fine when I run the code on real device, but when I do it in the APK, it partially works. Page has 4 tabs and the selected tab has blue color as opposed to white when not selected. i am on tab number 3 that is index number 2, and When re-route happens, eventually i have to come on the same tab. This is the code :
onPressed: () async {
// after Api calls
Get.back();
setState(() {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: ((context) =>
OffersScreenPage(
getIndex: 2,
offers: false,
collection: false,
shopoffers: true,
checkoffers: false,
))));
});
}
Get index takes us to tab number 3. Offers + collection + check offers become false ie white in color and shopOffers is true ie it is selected so it is blue in color.
What happens in APK is that the colors is same but the tab that is actually opened is tab number 2 that is index 1. How is this happening?
That's the title. My code requires a YouTube ID to go to the previous page, a favorite variable, a previous page button to go to the previous page, and a next page button to go to the next page, as shown in the code below.
LearnLevelButton(
color: favoriteButton_0_01_01 ? Colors.orange : Color(0xff7ba6f9),
text: '1-1',
onTap: () async {
await Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => Video(
YoutubeID: 'asfasdf23',
favorite: favoriteButton_0_01_01,
nextpage: Video(YoutubeID: '', nextpage: null,),
backpage:
favorite2: '_favoriteButton_0_01_01', text1: '', back: '',
),));
}
),
You may think you can create and use files for each page, but you used this method because you have to create hundreds of pages.
However, I quickly realized that my method was wrong.
If performed in the following manner, the next page information on the next page and the next page information on the next page are...In this way, the call code does not end because it requires endless information.
await Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => Video(
YoutubeID: 'asfasdf23',
favorite: favoriteButton_0_01_01,
nextpage: Video(YoutubeID: '', nextpage: null,...........),
backpage:
favorite2: '_favoriteButton_0_01_01', text1: '', back: '',
),));
Is there no other way?
The functions provided per page go to the next page, go to the previous question page, and return to the menu, YouTube ID, and favorite variables.
I am not sure how you implemented this. Please try the following.
Create a class
class VideoClass{
String youtubeID;
bool fav;
int currentIndex;
VideoClass({this.youtubeID, this.fav, this.currentIndex});
}
Now create a list of this class like List<VideoClass> allVideoInfo = [];
Add info as required. allVideoInfo.add(new VideoClass(youtubeID:.....);
Now load a page with just index. And inside the page call the url like the following
allVideoInfo[widget.index].youtubeID If the user clicks on the fav button then change the value like allVideoInfo[widget.index].fav =! allVideoInfo[widget.index].fav;. Convert this list to a string using json.encode and save it in shared preferences. When you open the app for the first time. Use json.decode to get the value from shared prefs and use it.
When the user clicks on the next page. Get the current index and add 1 to it and pass it to the next page. Previous page like current index -1. That will be the best method to handle everything locally.
I'm working with ionic react and I want to use useIonViewDidEnter in the menu component but useIonViewDidEnter in the menu component doesn't work and nothing showing in the console, anyone can help, please?
const ManagerMenu: React.FC = () => {
useIonViewDidEnter(() => {
console.log('isAuthorizedToSeeContracts')
})
It only works in pages I believe.
I suggest you manage the authState either through a property, context, or something else.
Use case
hey everybody. my problem is calling callback only when a user drags the map in some direction and not when he taps on the marker. I was trying to add the solution described here.
gestureRecognizers: Set()
..add(Factory<DragGestureRecognizer>(() => Test(() {
myCallBack();
})),
but in this case, there is not any chance to separate gestures. My next effort was adding certain GestureRecognazers and assign myCallBack on onStart, onDown etc.
GoogleMap(
gestureRecognizers: Set()
..add(Factory<PanGestureRecognizer>(() => PanGestureRecognizer()..onUpadate = () {myCallback()}))
..add(Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()..onStart = () {myCallback()}))
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer()..onDown = () {myCallback()})),
but only function that called was onDown. and again it worked for absolutely all gestures including onTap. But I figured that the onUpdate should worked at least. but it didn't
I have a "list page". and an add page. User clicks "add page", goes to a new page where they add some entity. Then I pop the Navigator, and user goes back to "list page".
At this point, I want to get notified somehow - callback maybe? override a method, I am not really sure - and re-read the information from database.
Is there a hook like this in Flutter? Or is there another pattern that I should use?
The Navigator.push method returns a future of the generic type of the Route:
Navigator.of(context)
.push(new MaterialPageRoute<String>(...))
.then((String value) {
print(value);
});
And inside the new route, when you have the value you need:
Navigator.of(context).pop('String');
If at your list page, you create function let say retrieveData() to read list of the data then call it inside initState, if you're using pushNamed route, the simple solution would be
Navigator.pushNamed(context, '/adddatapage').whenComplete(retrieveData());
If you're using push route,
Navigator.of(context).push(new MaterialPageRoute(builder: (context) => AddPage())).whenComplete(retrieveData);
That should be enough. No need to additional code on the add page. This will be works if user press back button also, again, without additional code in the add page.
Adding a option to #ian 's answer
Navigator.of(context)
.push(new MaterialPageRoute<String>(...))
.then((value) => setState(() => {}));
This worked for me. This will rebuild whenever page is loaded.
Write below code when redirect to screen 2,
Navigator.pushNamed(context, '/screen2').then((_) {
// This block runs when you have returned back from screen 2.
setState(() {
// code here to refresh data
});
});
Use
Navigator.pop(context);
in screen 2 to back to screen 1
i use Navigator.pushAndRemoveUntil, it will refresh the page and load the data again, this is example :
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) =>
CustomerMainPage()),
(Route<dynamic> route) =>
false);
I passed a callback method into the "add" page as a Navigator route argument. The callback is a method in my list page. The "add" page executes the callback when exiting. The callback method then simply refreshes the data and calls setState to refresh the screen.
My architecture is using Provider and viewmodels, but it should be straight-forward in a standard app as well.
For named route:
Navigator.pushNamed(context, '/page2').then((_) {
// This block runs when you have returned back to the 1st Page from 2nd.
setState(() {
// Call setState to refresh the page.
});
});
For unnamed route:
Navigator.push(context, MaterialPageRoute(builder: (_) => Page2())).then((_) {
// This block runs when you have come back to the 1st Page from 2nd.
setState(() {
// Call setState to refresh the page.
});
});