Skip to content

Nested module should override parent binding #1021

@vgabler

Description

@vgabler

Describe the bug
If i have a singleton binding of type T, then navigate to a child module route wich also binds to this same T (but a different implementation), the returned instance inside this child module comes from the parent instead of overriding.

Environment
Flutter 3.32.2

Pubspec.yaml

name: test_sub_editor
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0

environment:
  sdk: ^3.8.1

dependencies:
  flutter:
    sdk: flutter
  flutter_modular: ^6.4.1

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^5.0.0

flutter:
  uses-material-design: true

To Reproduce
From new flutter empty application
Here is the minimal reproducible code:

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';

import 'modules.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(
    ModularApp(
      module: BaseModule(),
      child: MaterialApp.router(
        title: 'Child Module Bug',
        theme: ThemeData(primarySwatch: Colors.blue),
        routerConfig: Modular.routerConfig,
      ),
    ),
  );
}

modules.dart

import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';

import 'services.dart';

class BaseModule extends Module {
  @override
  void binds(Injector i) {
    i.addLazySingleton<GetHelloMessage>(GetHelloMessageBase.new);
  }

  @override
  void routes(RouteManager r) {
    r.child(
      '/',
      child: (context) => BasePage(
        title: "BASE MODULE",
        navigate: () => Modular.to.pushNamed("childModule/"),
      ),
    );
    r.module("/childModule/", module: ChildModule());
  }
}

class ChildModule extends Module {
  @override
  void binds(Injector i) {
    i.addLazySingleton<GetHelloMessage>(GetHelloMessageChild.new);
  }

  @override
  void routes(RouteManager r) {
    r.child(
      '/',
      child: (context) =>
          BasePage(title: "CHILD MODULE", navigate: () => Modular.to.pop()),
    );
  }
}

class BasePage extends StatelessWidget {
  const BasePage({super.key, required this.title, required this.navigate});

  final String title;
  final Function() navigate;

  @override
  Widget build(BuildContext context) {
    final getHelloMessage = Modular.get<GetHelloMessage>();

    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(getHelloMessage()),
            FilledButton(onPressed: navigate, child: Text("Navigate")),
          ],
        ),
      ),
    );
  }
}

services.dart

abstract class GetHelloMessage {
  String call();
}

class GetHelloMessageBase implements GetHelloMessage {
  @override
  String call() {
    return "Hello from BASE";
  }
}

class GetHelloMessageChild implements GetHelloMessage {
  @override
  String call() {
    return "Hello from CHILD";
  }
}

Expected behavior
The child module should prioritize it's own bindings instead of the parent's. In "Child Module" page, we should see the message "Hello from CHILD"

Screenshots

Image

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    newNew issue request attention

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions