skip to Main Content

I have one code for mobile and web app in Flutter. Only difference is using another method for navigation back (because some issue in flutter web).

  1. For web: js.context.callMethod(‘back’)
  2. For mobile: Navigator.pop(context);
import 'package:flutter/material.dart';
import 'dart:js' as js;  ///this is only for web

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home:  HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text("Homepage"),
      ),
      body: Container(),


      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => SecondPage()),
          );
        },
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text("Second page"),
      ),
      body: Container(),


      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.pop(context);  ///   for mobile
          js.context.callMethod('back');   /// for web
        },
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

}

I can’t build app for mobile using ‘dart:js’ and having method js.context.callMethod(‘back’) in code. Even if I have condition for platform.

What is good approach to do it?

2

Answers


  1. I’d use conditional imports. Put your web-only stuff on one side, and your non-web on the other.

    Login or Signup to reply.
  2. Dart provides a conditional import/export pattern, which is ideal for handling platform-specific code in Flutter apps. This can be applied to your scenario where you need different navigation methods for mobile and web.

    Directory Structure

    To start, you can organize your files like this:

    back/
    ├─ src/
    │  ├─ back_none.dart
    │  ├─ back_io.dart
    │  ├─ back_web.dart
    ├─ back.dart
    

    Implementation

    1. back_none.dart (for unsupported platforms)

      import 'package:flutter/widgets.dart';
      
      void back(BuildContext context) {
        throw UnimplementedError('The back function is not supported on this platform.');
      }
      

      This stub implementation ensures that if a platform is not supported, an error will be thrown, making it clear that the function is unavailable.

    2. back_io.dart (for mobile platforms)

      import 'package:flutter/widgets.dart';
      
      void back(BuildContext context) {
        Navigator.pop(context); // Handles the "back" action by popping the current route for mobile
      }
      

      This implementation uses Navigator.pop for mobile platforms, which handles the back navigation properly.

    3. back_web.dart (for web platforms)

      // ignore: avoid_web_libraries_in_flutter
      import 'dart:js' as js;
      import 'package:flutter/widgets.dart';
      
      void back(BuildContext context) {
        js.context.callMethod('back'); // Calls the JS method to navigate back in the browser
      }
      

      This implementation uses JavaScript’s window.history.back() to handle navigation in web browsers.

    4. back.dart (for conditional export)

      export 'src/back_none.dart' // Default stub implementation
          if (dart.library.io) 'src/back_io.dart' // Mobile (dart:io) implementation
          if (dart.library.js_util) 'src/back_web.dart'; // Web (dart:js) implementation
      

      This file conditionally exports the correct implementation based on the platform. The if directives ensure that only the relevant file for each platform is used.

    Usage

    Now, in the files where you want to use the back function, simply import it:

    import 'back/back.dart';
    
    ...
    
    FloatingActionButton(
      onPressed: () {
        back(context); // Calls the platform-specific back function
      },
      child: const Icon(Icons.arrow_back),
    )
    

    This approach ensures that your app runs on both mobile and web platforms without errors, as the appropriate navigation method will be selected based on the platform.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search