Coder Social home page Coder Social logo

flutterando / modular Goto Github PK

View Code? Open in Web Editor NEW
1.3K 39.0 250.0 8.51 MB

A smart project structure

Home Page: https://pub.dev/packages/flutter_modular

License: Other

Dart 69.96% Kotlin 0.08% Swift 1.17% Objective-C 0.03% HTML 2.67% CMake 9.35% C++ 14.70% C 0.81% Ruby 1.23%

modular's Introduction

Flutter Modular


Logo Logo

Welcome to Flutter Modular! A smart project structure.

View Example · Report Bug · Request Feature



Table of Contents
  1. About The Project
    1. What is Modular?
    2. Ready to get started?
    3. Common questions
  2. Usage
    1. Starting a project
    2. The ModularApp
    3. Creating the Main Module
  3. Contributing
  4. Contact
  5. Contributors


📝 About The Project

Let's find out how to implement a Modular structure in your project.

What is Modular?

Modular proposes to solve two problems:

  • Modularized routes.
  • Modularized Dependency Injection.

In a monolithic architecture, where we have our entire application as a single module, we design our software in a quick and elegant way, taking advantage of all the amazing features of Flutter💙. However, producing a larger app in a "monolithic" way can generate technical debt in both maintanance and scalability. With this in mind, developers adopted architectural strategies to better divide the code, minimizing the negative impacts on the project's maintainability and scalability..

By better dividing the scope of features, we gain:

  • Improved understanding of features.
  • Less breaking changes.
  • Add new non-conflicting features.
  • Less blind spots in the project's main business rule.
  • Improved developer turnover.

With a more readable code, we extend the life of the project. See example of a standard MVC with 3 features(Auth, Home, Product):

A typical MVC

.
├── models                                  # All models      
│   ├── auth_model.dart                     
│   ├── home_model.dart                     
│   └── product_model.dart         
├── controller                              # All controllers
│   ├── auth_controller.dart                     
│   ├── home_controller.dart                     
│   └── product_controller.dart             
├── views                                   # All views
│   ├── auth_page.dart                     
│   ├── home_page.dart                     
│   └── product_page.dart                   
├── core                                    # Tools and utilities
├── app_widget.dart                         # Main Widget containing MaterialApp 
└── main.dart                               # runApp 

Here we have a default structure using MVC. This is incredibly useful in almost every application.

Let's see how the structure looks when we divide by scope:

Structure divided by scope

.                  
├── features                                 # All features or Modules 
│   ├─ auth                                  # Auth's MVC       
│   │  ├── auth_model.dart   
│   │  ├── auth_controller.dart  
│   │  └── auth_page.dart                      
│   ├─ home                                  # Home's MVC       
│   │  ├── home_model.dart   
│   │  ├── home_controller.dart  
│   │  └── home_page.dart                        
│   └─ product                               # Product's MVC     
│      ├── product_model.dart   
│      ├── product_controller.dart
│      └── product_page.dart                    
├── core                                     # Tools and utilities
├── app_widget.dart                          # Main Widget containing MaterialApp 
└── main.dart                                # runApp 

What we did in this structure was to continue using MVC, but this time in scope. This means that each feature has its own MVC, and this simple approach solves many scalability and maintainability issues. We call this approach "Smart Structure". But two things were still Global and clashed with the structure itself, so we created Modular to solve this impasse.

In short: Modular is a solution to modularize the route and dependency injection system, making each scope have its own routes and injections independent of any other factor in the structure. We create objects to group the Routes and Injections and call them Modules.

Ready to get started?

Modular is not only ingenious for doing something amazing like componentizing Routes and Dependency Injections, it's amazing for being able to do all this simply!

Go to the next topic and start your journey towards an intelligent structure.

Common questions

  • Does Modular work with any state management approach?

    • Yes, the dependency injection system is agnostic to any kind of class including the reactivity that makes up state management.
  • Can I use dynamic routes or Wildcards?

    • Yes! The entire route tree responds as on the Web. Therefore, you can use dynamic parameters, query, fragments or simply include a wildcard to enable a redirect to a 404 page for example.
  • Do I need to create a Module for all features?

    • No. You can create a module only when you think it's necessary or when the feature is no longer a part of the scope in which it is being worked on.

✨ Usage

flutter_modular was built using the engine of modular_core that's responsible for the dependency injection system and route management. The routing system emulates a tree of modules, just like Flutter does in it's widget trees. Therefore we can add one module inside another one by creating links to the parent module.

Starting a project

Our first goal will be the creation of a simple app with no defined structure or architecture yet, so that we can study the initial components of flutter_modular

Create a new Flutter project:

flutter create my_smart_app

Now add the flutter_modular to pubspec.yaml:

dependencies:
  flutter_modular: any

If that succeeded, we are ready to move on!

💡 TIP: Flutter's CLI has a tool that makes package installation easier in the project. Use the command: (flutter pub add flutter_modular)

The ModularApp

We need to add a ModularApp Widget in the root of our project. MainModule and MainWidget will be created in the next steps, but for now let's change our main.dart file:

import 'package:flutter/material.dart';

void main(){
  return runApp(ModularApp(module: /*<MainModule>*/, child: /*<MainWidget>*/));
}

ModularApp forces us to add a main Module and main Widget. What are we going to do next? This Widget does the initial setup so everything can work as expected. For more details go to ModularApp doc.

💡 TIP: It's important that ModularApp is the first widget in your app!

Creating the Main Module

A module represents a set of Routes and Binds.

  • ROUTE: Page setup eligible for navigation.
  • BIND: Represents an object that will be available for injection to other dependencies.

We'll see more info about these topics further below.

We can have several modules, but for now, let's just create a main module called AppModule:

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

void main(){
  return runApp(ModularApp(module: AppModule(), child: <MainWidget>));
}

class AppModule extends Module {
  @override
  List<Bind> get binds => [];

  @override
  List<ModularRoute> get routes => [];
}

Note that the module is just a class that inherits from the Module class, overriding the binds and routes properties. With this we have a route and injection mechanism separate from the application and can be both applied in a global context (as we are doing) or in a local context, for example, creating a module that contains only binds and routes only for a specific feature!

We've added AppModule to ModularApp. Now we need an initial route, so let's create a StatelessWidget to serve as the home page.

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

void main(){
  return runApp(ModularApp(module: AppModule(), child: <MainWidget>));
}

class AppModule extends Module {
  @override
  List<Bind> get binds => [];

  @override
  List<ModularRoute> get routes => [
    ChildRoute('/', child: (context, args) => HomePage()),
  ];
}

class HomePage extends StatelessWidget {
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title: Text('Home Page')),
      body: Center(
        child: Text('This is initial page'),
      ),
    );
  }
}

We've created a Widget called HomePage and added its instances in a route called ChildRoute.

💡 TIP: There are two ModularRoute types: ChildRoute and ModuleRoute.

  • ChildRoute: Serves to build a Widget.
  • ModuleRoute: Concatenates another module.

🧑‍💻 Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the appropriate tag. Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Remember to include a tag, and to follow Conventional Commits and Semantic Versioning when uploading your commit and/or creating the issue.

(back to top)

💬 Contact

Flutterando Community

(back to top)


👥 Contributors

(back to top)

🛠️ Maintaned by


This fork version is maintained by Flutterando.

modular's People

Contributors

albertomonteiro avatar allanlucio avatar allcontributors[bot] avatar alvarovasconcelos avatar andredealmei avatar arthurgiani avatar ascenio avatar bmsrangel avatar bwolfs2 avatar camrongiuliani avatar crossbread avatar dependabot[bot] avatar devguusta avatar felipe-labbits avatar gabrielcr99 avatar gibahjoe avatar guikar741 avatar irvine5k avatar jacobaraujo7 avatar lucasnsa avatar lucioeduardo avatar marcoafc avatar mateusfccp avatar mex978 avatar pablo-threadable avatar pavel-sulimau avatar raphaelbarbosaqwerty avatar rogsilva avatar steniooliv avatar toshiossada avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

modular's Issues

The getter 'isInitialRoute' isn't defined for the class 'RouteSettings'

Estou iniciando um projeto com o Modular e estou com este erro. Alguém pode me ajudar ?

Tenho 2 módulos: Login e Home e uma página splash.

Meu AppModule está assim:
@override List<Router> get routers => [ Router('/', child: (_, args) => SplashPage()), Router(Routes.PAGE_HOME, module: HomeModule()), Router(Routes.PAGE_LOGIN, module: LoginModule()), ];

Compiler message:
../../../.pub-cache/hosted/pub.dartlang.org/flutter_modular-0.5.2/lib/src/modular_base.dart:372:18: Error: The getter 'isInitialRoute' isn't defined for the class 'RouteSettings'.

  • 'RouteSettings' is from 'package:flutter/src/widgets/navigator.dart' ('../../flutter/packages/flutter/lib/src/widgets/navigator.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'isInitialRoute'.
    if (settings.isInitialRoute) {
    ^^^^^^^^^^^^^^
    Target kernel_snapshot failed: Exception: Errors during snapshot creation: null
    Failed to build bundle.

_debugLocked

Adaptei ao projeto do jacob de login e dá o seguinte erro:
Failed assertion: line 2335 pos 12: '!_debugLocked': is not true.

disposer = autorun((_) {
      final auth = Modular.get<AuthController>();
      if (auth.status == AuthStatus.Authenticated) {
        Modular.to.pushReplacementNamed('/home');
      } else if (auth.status == AuthStatus.NotAuthenticated) {
        print('eveio');
        Modular.to.pushReplacementNamed('/login');
      }
    });

só consegui rodar utilizando

Timer.run(() {
   Modular.to.pushReplacementNamed('/home');
});

Problemas com o rotamento

Problemas de roteamento

Olá, boa tarde!
Estou com um problema de roteamento nomeado. Quando navego do HomeModule para o RouteOneModule (home/route-one) não tenho problemas, porém o problema está na navegação do RouteOneModule para o RouteTwoModule (home/route-one/route-two), onde recebo um erro de Stack Overflow

I/flutter (22815): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter (22815): The following StackOverflowError was thrown while handling a gesture:
I/flutter (22815): Stack Overflow
I/flutter (22815): 
I/flutter (22815): When the exception was thrown, this was the stack:
I/flutter (22815): #1      String._setRange (dart:core-patch/string_patch.dart)
I/flutter (22815): #2      _StringBase.replaceRange (dart:core-patch/string_patch.dart:606:22)
I/flutter (22815): #3      _StringBase.replaceFirst (dart:core-patch/string_patch.dart:593:12)
I/flutter (22815): #4      Modular._searchInModule (package:flutter_modular/src/modular_base.dart:170:43)
I/flutter (22815): #5      Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
I/flutter (22815): #6      Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
I/flutter (22815): #7      Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
I/flutter (22815): #8      Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
I/flutter (22815): #9      Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
I/flutter (22815): #10     Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
I/flutter (22815): #11     Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
I/flutter (22815): #12     Modular._searchInModule (package:flutter_modular/src/modular_base.dart:184:20)
...

O que estou tentando é concatenar as rotas home/route-one/route-two

A navegação é feita por RaisedButton, tanto na HomePage quanto na RouteOnePage

RaisedButton(
              child: Text('Route One -->'),
              onPressed: (){
                Navigator.pushNamed(context, '/route-one');
              },
            ),

O projeto que fiz é simples, que fiz somente para testar a navegação por rotas nomeadas. Este é o link do projeto no GitHub

Testing widget with mock 'store'

Hi, thanks for amazing lib!

I'm trying to find a way to test a separate widget which use "store". Is there a way to wrap separate widget to mocked "store"

For example, i have AuthModule

class AuthModule extends MainModule {

  @override
  List<Bind> get binds => [
    Bind((i) => AuthStore())
  ];
  ....
  @override
  Widget get bootstrap => AppWidget();
}

And i have widget witch use AuthStore

class LoginForm extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    final store = Modular.get<AuthStore>();
    //...
  }
}

How to mock AuthStore if i want to test only LoginForm widget? I did find this point in documentation.

question: how to inject some instance with Type T?

sample:
A forms have tree form. each one need a service T.


I want create a Class TFactory, which is used to switch argument to specific instance.
Then, FormModule.bind is TFactory.

  • how to use:
    get TFactory first, then, get specific instance

is it a good way?

PS: TFactory is someone like kiwi

container.registerInstance<Character, Sith>(Sith('Anakin', 'Skywalker'), name: 'DartVader');

ModularError: Recursive calls detected

A validação de recursividade nos Binds está sendo disparada em um caso onde não deveria. Segue um exemplo:

List get binds => [
Bind((i) => Dependence01()),
Bind((i) => Dependence02(i.get<Dependence01>())),
Bind((i) => Dependence03(i.get<Dependence01>(), i.get<Dependence02>())),
Bind((i) => HomeController(i.get<Dependence03>())),
];
Desenho sem título

Se eu não estiver errado, o problema ocorre pois a validação se baseia em uma lista simples de "Types", onde não se pode repetir o "Type". No exemplo acima, o type "Dependence01" está sendo adicionado duas vezes nesta lista de controle. Para que não ocorra o erro, talvez, a validação deva ser feita para cada linha da árvore de dependências, individualmente.
HomeController > Dependence03 > Dependence01
HomeController > Dependence03 > Dependence02 > Dependence01

What is the proper way to reset all module bindings after each test?

I'm getting some errors when I run an entire test file using "flutter test", but each test passes if tested individually.

So, I realized that it happens because my controller (a Mobx Store generated with Slidy) is not being recreated each time I call InitModules() inside setUp() function. The controller seems to be a singleton that is retrieved each time I call Modular.get() and even a call to initModules() can't recreate the controller.

By not being recreated after each test, the controller keeps dirty data from the previous test when starting a new test, leading to undesirable behavior.

Let me share some code to clarify what I'm trying to achieve.

The tests file:

main() {
  setUp((){   
    // does not reload the entire module, the controller keeps its state after each test
    initModule(AuthModule());
  });
  testWidgets('test 1') ...
  testWidgets('test 2') ...
  testWidgets('test 3') ...
  group('group 1', () {    
      testWidgets('test 4') ...
      testWidgets('test 5') ...
  });
  testWidgets('test 6') ...

The Module:

class AuthModule extends ChildModule {
  @override
  List<Bind> get binds => [
        Bind((i) => LoginErrorStateController()),
        Bind((i) => LoginController()),
      ];

  @override
  List<Router> get routers => [
        Router('/', child: (_, args) => LoginPage()),
      ];

  static Inject get to => Inject<AuthModule>.of();
}

Inside the page, where the controller is retrieved using Modular:

class LoginPage extends StatefulWidget {
  final String title;
  const LoginPage({Key key, this.title = "Login"}) : super(key: key);

  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  LoginController controller = Modular.get<LoginController>();
  ...

Should initModule(AuthModule()) restart the entire module, including its binds, or this is out of the scope of this function?

What's the best practice to reset the whole module (including its bindings) before starting a new widget test? To achieve this behavior, I'm currently using this code, but I'm not sure this is the more efficient way to do this.

setUp((){
    // Removes the entire module
    Modular.removeModule(AuthModule());
    // Restart the module
    initModule(AuthModule());
  });

Thanks in advance.

Quando navega com pushNamed, ao voltar sem replacement, o build dos widgets vai incrementando o número de execuções

@jacobaraujo7 , Não sei se tem relação com esse mesmo problema de navegação que discutimos nessa issue: #11, mas com certeza tem a ver com questões de navegação.

Veja esses 2 videos:
https://drive.google.com/file/d/15ChEryT-w_2GbQL1d29efEao5z_Y_5Q0/view?usp=sharing

https://drive.google.com/file/d/1E-rEo4kIlk1vz71zX8WGDnXS_2R1N97C/view?usp=sharing

Quando navego pra outra tela com pushNamed, e depois retorno, o build dos widgets é executado em duplicidade, e a cada vez que navega e volta aumenta mais um execução do build. Minha tela ai no video tá com 7 widgets do mesmo, e após 10 vezes que navegou pra outra tela e voltou, tem 70 builds executados (10 pra cada um dos widgets) sendo que era pra ser só 1... isso com o tempo vai pesar pra caramba na performance pois basicamente todos os widgets da tela estão rodando o build mais vezes conforme vai navegando... correto ?

No primeiro video,naveguei pra outra tela usando pushNamed e retornei usando popAndPushNamed. No caso eu mudei pra pop e parou de aumentar os renders... Isso que eu não entendi, se a tela já tá no histórico de navegação e se eu navego pra ela de novo não teria que remover a parte antiga do histórico ?

No segundo video mesma coisa, estava navegando pushNamed, e nesse caso eu realmente quero manter o histórico pra retornar, não quero usar replacement, nem apagar o histórico da navegação. Mas aí começa a novela da repetição do build... Eu quero manter o a página Home carregada pois ela é o carro chefe do app e e tem muita coisa acontecendo nela pra ficar sendo recriada do zero. E só parou de incrementar as vezes que o build dela e dos widgets que tão nela quando usei Navigator.pushNamedAndRemoveUntil(context, '/outratela', ModalRoute.withName('/outratela')); na navegação...

Quais as ações possíveis pra melhorar essa questão de navegação e evitar esse processamento excessivo?

Pedantic Analysis Options

Adicionar padrão Pedantic nos códigos gerados

Ao gerar uma page colocar o construtor antes de todas as declarações. e colocar Aspas Simples no this.title da page gerada.

final String title;
const HomePage({Key key, this.title = "Home"}) : super(key: key);

to

const HomePage({Key key, this.title = 'Home'}) : super(key: key);
final String title;

Mudar para Aspas Simples nos Testes gerados:

test("First Test") to test('First Test')

Colocar Return type no main dos testes

main() to void main() 

Control over the route after it changes

Hi, when I used to create some InheritedWidgets and place them between the GenerateRoute method and the route resolve so I could create my own default implementation of something that depends on a context (default widget that a Flushbar shows, for example).

static dynamic pageBuilder(Widget widget) =>
MaterialPageRoute(builder: (
) => ExampleInheritedWidget(child: widget));

I know that if I do something like this with the mondule concept is probably going to be wrong, because of adding a dependency for any child that uses it, can't we create a method for the child module so we can "setup" the route after it change?

  @override
  List<Router> get routers => [
        Router('/', child: (_, args) => HomePage()),
      ];

then

 @override
 thatMethod(routeToRender) => ExampleInheritedWidget(child: routeToRender); 

This is just easier way of doing that, I think that placing the ExampleInheritedWidget as a parent of all the routes manually is too much.

Thanks!

Error add route

Error when calling the route using Modular.to.pushNamed

My code

Works well
Navigator.pushNamed(context, '/datail/${homeController.text}');

Does not work
Modular.to.pushNamed('/datail/${homeController.text}');

App Module

@override List<Router> get routers => [ Router('/', child: (_, args) => HomePage()), Router('/datail/:text', child: (_, args) => DatailPage( text: args.params['text'], )), ];

Error

Add Modular.navigatorKey in your MaterialApp;
return MaterialApp(
navigatorKey: Modular.navigatorKey,
...
.
'package:flutter_modular/src/modular_base.dart':
Failed assertion: line 94 pos 9: '_navigatorKey != null'

Uso do modular com o Get ou componente que atribua a navigatorKey

Ontem a partir do vídeo do Darlan no canal, gostei muito do Get e decidi usar o modal dele, achei simples e muito legal, já que as rotas estou utilizando as do próprio Modular e funcionam perfeitamente. Mas percebi que se eu usar um componente do mesmo tipo, Modular ou Get ou outro afim que eu tenha que setar a propriedade navigatorKey do MaterialApp, em ambos, tanto o Get quanto o Modular temos que passar o navigatorKey gerado pelo componente. Caso eu escolha um deles, o outro para de funcionar pq desconhecerá a key gerada pelo outro componente.

Eu não observei nenhuma propriedade ou método no Modular para que eu possa passar pra ele o key que deve usar.

Coçou a mão da POG para fazer funcionar os 2 juntos.

Não sei se terá implicações em outras partes do Modular, mas no pouco que testei o meu app funcionou com os 2 juntos e certinho minhas rotas voltaram a funcionar.

O que eu fiz:
No modular_base.dart acrescentei:

static set navigatorKey(GlobalKey<NavigatorState> key) => _navigatorKey = key;

A qual eu pego da key que o Get gera e no MaterialApp eu passo:

GlobalKey<NavigatorState> keyget = Get.key;
Modular.navigatorKey = keyget;
navigatorKey: keyget,

Bom, estou passando aqui e não no Get pela facilidade de relato em português, só isso. rs. Conheço inglês mas relatar tudo ia ser bem difícil.

How to get current route name?

Hi,

I'm developing an app that involves chat. When the user is in chat route and clicks on notification that directs to the same chat route with a different, say, id, I need to replace existing route with a new one instead of pushing on top.
As things are currently standing, Navigator doesn't expose an API for getting the current route name.

How can I achieve this in Modular?

Tem horas que mesmo saindo de um módulo, ele não tá executando dispose.

Boa tarde, tem horas que mesmo saindo de um módulo, ele não tá executando dispose. Veja um exemplo de uma rota:

AppModule

List<Router> get routers => [
        ...
        Router('/profile', module: ProfileModule()),
      ];

ProfileModule

@override
  List<Router> get routers => [
        Router('/', child: (_, args) => ProfilePage()),
        Router('/edit', child: (_, args) => ProfileEditPage()),
        Router('/about', child: (_, args) => ProfileAboutPage()),
      ];

No meu app, primeiro entra no ProfilePage pra exibir os dados, e exibe uma opção para exibir detalhes (/profile/about) ou editar o perfil(/profile/edit)... E pelo botão voltar que é colocado na AppBar, vai seguindo a stack das rotas até retornar pra tela anterior à carga do /profile aqui o comportamento tá certinho... mas se tento navegar pra fora, com um pushReplacementNamed, popAndPushNamed etc, navega pro novo destino fora da rota /profile mas não dá dispose no módulo.

Nesse caso eu devo forçar o dispose de alguma forma antes de navegar pra fora da rota ?

RouteGuard is never fired

class AppModule extends MainModule {
  @override
  List<Bind> get binds => [
        Bind((i) => AppController()),
      ];
  @override
  List<Router> get routers => [
        Router('/', module: LoginModule()),
        Router('/home', module: HomeModule(), guards: [AppGuard()]),
      ];
  @override
  Widget get bootstrap => AppWidget();
  static Inject get to => Inject<AppModule>.of();
}

class AppGuard implements RouteGuard {
  @override
  bool canActivate(String url) {
    return false;
  }
}

Fala pessoal, mesmo forçando retorno para false e debugando, o canActivate não esta sendo acionado, a implementação do RouteGuard está correta?
Teria algum outro material/documentação para olhar sobre segurança de rotas?

Abraço!

ModularState calls the same instance

I understand that the ModularState was designed to work only with the view, and dispose with it. And I don't want to change that. But let's see an example:

Imagine a Login View. With a bar with "login credentials" or the option to fill email+password. Then I detach that "credentials bar" and create a new widget for it.

Or I should make micro controllers for each widget like that. Or I should put that controller on Bind. But I just want that any ModularState child have access to it's father controllers.

Makes sense?

Navegação pegando Rota Errada

Nesse caso eu tenho a rota "/:title" e a rota "/dash"

Quando faça a navegação Modular.to.pushNamed("/dash") ele pega a primeira rota e coloca o :title como Dash.

Ps: Tambem acontece com Navigator.of(Context)

image

Criação de um serviço de navegação para trabalhar sem o Context da Aplicação

Queria saber o que vocês acham disso.
Seria interessante criar um NavigatorService em que possamos injetar e pegar em qualquer parte do aplicativo sem a necessidade do context.
Gostaria de saber se isso traria alguma implicação, principalmente na abertura de dialogs e Snackbar de cada página.

A ideia é fugir da arvore de elementos mais uma vez para possibilitar o uso dos metodos de navegação em uma classe controller.

Podemos chegar a isso trabalhando com uma Globalkey no MaterialApp, nos fornecendo tudo oq precisamos.
O que acham disso?

Use the GLOBAL flag in BINDS on any Module

I have a suggestion, even if it comes from me it doesn't mean it's good...
I would like to use a global flag in any module. This would make Bind global and work even if the Module had not been called. Roughly speaking, it would be as if it were in the AppModule even though it is in a child Module, being accessible to any other module.

class LoginModule extends ChildModule {
    
     @override
      List<Bind> get binds => [
           Bind((i) => AuthStore(), global: true),
     ]
   
   ....
}

In this example, AuthStore would be visible to the entire application even if LoginModule is not instantiated.
Ai would not need to put the AuthStore in the Bind of the AppModule, as it would already be global. In practice it would work as if it were in the AppModule.

Is that a good idea?

Sharing

This looks nice.

I would like to see what you think about Shaing as its so related to Routing and Security.

  1. On Desktop we need to share between apps
  2. On Web, if they have the Desktop or Mobile app, it should redirect to that.
  3. Sharing scheme. So you can control a bit more what is shared to what.

We have started to research dong all this here: https://github.com/getcouragenow/plugins/tree/master/links

Maybe we can collaborate on adding this to the Modular project if its wanted.

Modular.args referencia do objeto incorreta

apos a adição do Modular.args tive um problema em algumas paginas que passavam argumentos pelo Modular.to.pushNamed("rota", arguments: Objeto). o problema acontece quando apos passar o objeto A da pagina 1 para 2 e passar outro objeto B da pagina 2 para 3 ao voltar para pagina 2 o objeto B é passado de volta para pagina 2 causando erro pois a pagina 2 esperava o objeto A não o objeto B que ela mandou para pagina 3.

Captura de tela de 2020-02-12 14-24-33

Antes da atualização do Modular.args funcionava sem problema pois sempre recebia a referencia correta do objeto.

Uma sugestão para os testes dos módulos que recebem os argumentos pelo Modular.args é implementar uma função como essa no modular_base.dart para possibilitar a passagem de parâmetros ao testar as paginas ou controllers.

  @visibleForTesting
  static void arguments({Map<String, dynamic> params, dynamic data}) {
    _args = ModularArguments(params ?? {}, data);
  }

Clear injected objects before super.dispose()

We have a small issue in the ModularApp widget as we are calling the function that dispose the injected object after the super.dispose() function.

  @override
  void dispose() {
    super.dispose();
    widget.module.cleanInjects();
    print("-- ${widget.module.runtimeType.toString()} DISPOSED");
  }

We also have the same issue in the consumer_widget class:

@override
  void initState() {
    _inject = widget.inject ?? Inject();
    value = _inject.get<T>();
    value.addListener(listener);
    super.initState();
  }

Is possible implement nested routes using modular?

Hi, thank you for this package!

Is possible implement nested route using modular?

I need of tab bar and every widget must have our routes
I want try new different approach using Modular instead classic method using navigator inside the widget screen.

Thanks

Como passar argumentos por Modules

Olá,

Estou tentando passar um argumento no Router para um Module, não para um Widget simples, porém não existe essa opção (ou não encontrei).
Existe essa possibilidade?

Example crashing when click in 'list'

Ajust needed on home_modular.dart, line 23 at example/lib/app/modules/home

from:
param: args.params['id'],

to:
param: int.parse(args.params['id']),

Navegação Nativa

Seria interessante adicionar a navegação nativa para CupertinoApps ou que fosse passado como parâmetro e, desta forma manter a coerência no app.
Ademais, parabéns pelo trabalho.

How to test navigation with Modular?

Does Modular provide some features to test navigation?

I'd like to test if the application properly navigates to another route when the user taps a button.

On the button pressed event, there's a command:

Modular.to.popAndPushNamed('/home');

How could I create some test-case to ensure that the button tap event navigates to another screen correctly?

Thanks in advance.

Add option to hide Prints

image

Precisamos adicionar uma opção para esconder os Prints em modo Debug, e nunca mostrar em modo Release ( Em release ano passado vi alguns apps da loja rodando prints no meu console quando conectado no VSCode)

Nested Routes

Is it possible to be have nested routes while preserving the state of Navigators?

Initializing a module two times when app starts

Every time that I restart my app and go to the main menu ("/menu" route), the module Identify is initialized two times and one of them is disposed. I already search for what I am missing and didn't find anything. Please help me.

Restarted application in 1,806ms.
I/flutter (11409):
I/flutter (11409): *** Modular Routers ***
I/flutter (11409):
I/flutter (11409): /                              => SplashPage
I/flutter (11409): /menu                          => MenuPage
I/flutter (11409): /recipes                      => RecipesPage
I/flutter (11409): /register                     => RegisterPage
I/flutter (11409): /identify                     => IdentifyPage
I/flutter (11409): /identify/fill_data            => FillDataPage
I/flutter (11409): /identify/driver_data          => DriverDataPage
I/flutter (11409): /recipes/authorization_details => AuthorizationDetailsPage
I/flutter (11409):
I/flutter (11409): *****
I/flutter (11409):
I/flutter (11409): -- AppModule INITIALIZED
I/flutter (11409): building menu
I/flutter (11409): building menu
I/flutter (11409): -- IdentifyModule INITIALIZED
I/flutter (11409): -- IdentifyModule INITIALIZED
I/flutter (11409): -- IdentifyModule DISPOSED

My MenuPage source code:

class MenuPageState extends ModularState<MenuPage, MenuController> {
  AuthController _authController = Modular.get<AuthController>();

  @override
  void initState() {
    super.initState();
    controller.selectedDrawerIndex = 0;
    controller.pageController = PageController(initialPage: 0);
  }

  @override
  void dispose() {
    super.dispose();    
  }

  List<DrawerItem> drawerItems = [
    DrawerItem(
      title: 'Abastecimento',
      icon: Icons.directions_car,
    ),
    DrawerItem(
      title: 'Comprovantes',
      icon: Icons.print,
    ),
    DrawerItem(
      title: 'Sair',
      icon: Icons.input,
    ),
  ];

  @override
  Widget build(BuildContext context) {
    print("building menu");
    return Scaffold(
      appBar: AppBar(
        title: Text(drawerItems[controller.selectedDrawerIndex].title),
      ),
      body: PageView(
          physics: NeverScrollableScrollPhysics(),
          controller: controller.pageController,
          children: [
            RouterOutlet(
              module: IdentifyModule(),
              keepAlive: false,
            ),
            RouterOutlet(
              module: RecipesModule(),
              keepAlive: false,
            ),
          ]),
      drawer: Drawer(
        child: ListView(
          children: <Widget>[
            DrawerHeader(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Container(
                      margin: EdgeInsets.symmetric(vertical: 12.0),
                      child: Image.asset("assets/icons/Ativo16.png")),
                  Container(
                    margin: EdgeInsets.symmetric(vertical: 12.0),
                    child: Column(
                      children: <Widget>[
                        Text(
                          "${_authController.userModel.companyName}",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                              color: Theme.of(context).primaryColor,
                              fontSize: 16,
                              fontWeight: FontWeight.bold),
                        ),
                        Text(
                          "${_authController.userModel.companyId}",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                              color: Theme.of(context).primaryColor,
                              fontSize: 12,
                              fontWeight: FontWeight.bold),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemCount: drawerItems.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    leading: Icon(drawerItems[index].icon),
                    title: Text(drawerItems[index].title),
                    selected: index == controller.selectedDrawerIndex,
                    onTap: () {
                      controller.onSelectItem(index);
                    },
                  );
                })
          ],
        ),
      ),
    );
  }
}

All code is working, but when I initialize this is happening and it bothers me

Modular Navigator triggered when resizing window ??

Hello everyone,

Thanks for your awesome package, I love it!! 🔥

I encounter a litte issue right now and I'm not sure why it's happening, could you provide any support ? 🙏
I'm trying to make my app responsive using responsive_builder and it works, but not when I just split my content in different screens.. Now when on a child route of a ChildModule I try to resize windows, first pixel changed, and modular redirect to Modular.initialRoute of this ChildModule..

Tell me what you need to investigate!!
I pushed the code in a personal repo, you can check it out here. Also app is being served here!

I guess it's because the size of window being changed, my Layout (Navbar on top and body content) is being notified so it tries to rebuild, and all my routes are under this? 🤔
This is the output:
rECQwfGQwE

Dispose not being called on module after navigating to another one

Like I talked to @jacobaraujo7 ,

The scenario is like this:

  1. App starts in HomeModule ("/")
  2. Navigate to NewPage in NewModule ("/new") with Modular.to.pushNamed('/new')
  3. Navigate to Page2 in NewModule ("/new/page2") with Modular.to.pushNamed('/new/page2')
  4. Navigate back to HomeModule ("/") with Modular.to.pushReplacementNamed('/')

When executing step 4, it should dispose NewModule, but it never happens. That can cause issues when navigating back to NewModule.
It only disposes correctly if I navigate to "/" inside the "/new" route (first route inside NewModule), if I try to navigate from 2+ page in stack, it doesn't dispose. You can test this scenario uncometing the line 24 inside new_page.dart

Minimal reproducible project:
https://github.com/Gustav0ar/modular_route_bug

Route navigation not working for routes declared outside AppModule

I'm getting the following error when trying to navigate to routes declared outside AppModule:

Could not find a generator for route RouteSettings("/product/1/select-cut-type", null) in the _WidgetsAppState.

app_module.dart

@override
  List<Router> get routers => [
        Router('/', module: HomeModule()),
        Router('/product', module: ProductModule()),
      ];

product_module.dart

@override
  List<Router> get routers => [
        Router('/:id', child: (_, args) => ProductPage(id: args.params['id'])),
        Router('/:id/select-cut-type ', child: (_, args) => SelectCutTypePage(id: args.params['id'])),
      ];

Inside ProductPage, I try to navigate to SelectCutTypePage using the following command:
Modular.to.pushNamed('/product/$id/select-cut-type');

It works fine if I declare the route inside AppModule like this:

@override
  List<Router> get routers => [
        Router('/', module: HomeModule()),
        Router('/product', module: ProductModule()),
        Router('/product/:id/select-cut-type', child: (_, args) => SelectCutTypePage(id: args.params['id']))),
      ];

EDIT 1:
Forgot to add ProductPage content:

import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:pedras_mobile/app/modules/product/select_cut_type/select_cut_type_controller.dart';

class SelectCutTypePage extends StatefulWidget {
  final String title;
  final String id;
  const SelectCutTypePage({Key key, this.title = "SelectCutType", this.id}) : super(key: key);

  @override
  _SelectCutTypePageState createState() => _SelectCutTypePageState();
}

class _SelectCutTypePageState extends ModularState<SelectCutTypePage, SelectCutTypeController> {
  //use 'controller' variable to access controller

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: <Widget>[],
      ),
    );
  }
}

Stack Overflow

Hoje, domingo 16/02/2020, executando a mesma versão da sexta, me deparei com o seguinte erro:

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Stack Overflow

Esse erro aconteceu sem eu ter mexido em meu app.

Ocorre quando chamo uma rota nomeada :

  • Modular.to.pushReplacementNamed('/login');

Percebi que disponibilizaram nova versão este fim de semana.

Poderiam ver o que houve?

Abcs,
Luiz Leite


Launching lib\main.dart on SM J320M in debug mode...
√ Built build\app\outputs\apk\debug\app-debug.apk.
D/FlutterActivityAndFragmentDelegate(13747): Setting up FlutterEngine.
D/FlutterActivityAndFragmentDelegate(13747): No preferred FlutterEngine was provided. Creating a new FlutterEngine for this FlutterFragment.
D/FlutterActivityAndFragmentDelegate(13747): Attaching FlutterEngine to the Activity that owns this Fragment.
D/FlutterView(13747): Attaching to a FlutterEngine: io.flutter.embedding.engine.FlutterEngine@32f4f2a1
D/FlutterActivityAndFragmentDelegate(13747): Executing Dart entrypoint: main, and sending initial route: /
I/flutter (13747): Platform: Android
I/flutter (13747):
I/flutter (13747): *** Modular Routers ***
I/flutter (13747): / => SplashPage
I/flutter (13747): /login => LoginPage
I/flutter (13747): /cadUser => CadUserListPage
I/flutter (13747): /dashboard => DashboardPage
I/flutter (13747): /catalogo => CatalogoPage
I/flutter (13747): /cadUser/detalhes => CadUserEditPage
I/flutter (13747): /catalogo/detalhes => DetalhesPage
I/flutter (13747):
I/flutter (13747): *****
I/flutter (13747): -- AppModule INITIALIZED
E/flutter (13747): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Stack Overflow
�[38;5;248mE/flutter (13747): #0 Modular._getInjectableObject�[39;49m
�[38;5;248mE/flutter (13747): #1 Modular.get�[39;49m
�[38;5;248mE/flutter (13747): #2 Inject.get�[39;49m
�[38;5;248mE/flutter (13747): #3 AppModule.binds.�[39;49m
�[38;5;248mE/flutter (13747): #4 ChildModule.getBind�[39;49m
�[38;5;248mE/flutter (13747): #5 Modular._getInjectableObject�[39;49m
�[38;5;248mE/flutter (13747): #6 Modular.get�[39;49m
�[38;5;248mE/flutter (13747): #7 new UserModel�[39;49m
�[38;5;248mE/flutter (13747): #8 new _LoginControllerBase�[39;49m
E/flutter (13747): #9 new LoginController (package:meuapp/app/modules/login/login_controller.dart)
�[38;5;248mE/flutter (13747): #10 AppModule.binds.�[39;49m
�[38;5;248mE/flutter (13747): #11 ChildModule.getBind�[39;49m
�[38;5;248mE/flutter (13747): #12 Modular._getInjectableObject�[39;49m
�[38;5;248mE/flutter (13747): #13 Modular.get�[39;49m
�[38;5;248mE/flutter (13747): #14 new UserModel�[39;49m
�[38;5;248mE/flutter (13747): #15 new _LoginControllerBase�[39;49m
E/flutter (13747): #16 new LoginController (package:meuapp/app/modules/login/login_controller.dart)
�[38;5;248mE/flutter (13747): #17 AppModule.binds.�[39;49m
�[38;5;248mE/flutter (13747): #18 ChildModule.getBind�[39;49m
�[38;5;248mE/flutter (13747): #19 Modular._getInjectableObject�[39;49m
�[38;5;248mE/flutter (13747): #20 Modular.get�[39;49m
�[38;5;248mE/flutter (13747): #21 new UserModel�[39;49m
�[38;5;248mE/flutter (13747): #22 new _LoginControllerBase�[39;49m
E/flutter (13747): #23 new LoginController (package:meuapp/app/modules/login/login_controller.dart)
�[38;5;248mE/flutter (13747): #24 AppModule.binds.�[39;49m
�[38;5;248mE/flutter (13747): #25 ChildModule.getBind�[39;49m
�[38;5;248mE/flutter (13747): #26 Modular._getInjectableObject�[39;49m
�[38;5;248mE/flutter (13747): #27 Modular.get�[39;49m
�[38;5;248mE/flutter (13747): #28 new UserModel�[39;49m
�[38;5;248mE/flutter (13747): #29 new _LoginControllerBase�[39;49m
E/flutter (13747): #30 new LoginController (package:meuapp/app/modules/login/login_controller.dart)
�[38;5;248mE/flutter (13747): #31 AppModule.binds.�[39;49m
�[38;5;248mE/flutter (13747): #32 ChildModule.getBind�[39;49m
�[38;5;248mE/flutter (13747): #33 Modular._getInjectableObject�[39;49m
E/flutter (13747): ...
E/flutter (13747): ...
�[38;5;248mE/flutter (13747): #18149 ChildModule.getBind�[39;49m
�[38;5;248mE/flutter (13747): #18150 Modular._getInjectableObject�[39;49m
�[38;5;248mE/flutter (13747): #18151 Modular.get�[39;49m
�[38;5;248mE/flutter (13747): #18152 AppWidget._getDeviceID�[39;49m
�[38;5;244mE/flutter (13747): #18153 _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:45:6)�[39;49m
�[38;5;248mE/flutter (13747): #18154 AppWidget._getDeviceID�[39;49m
�[38;5;248mE/flutter (13747): #18155 AppWidget.build�[39;49m
�[38;5;244mE/flutter (13747): #18156 StatelessElement.build�[39;49m
�[38;5;244mE/flutter (13747): #18157 ComponentElement.performRebuild�[39;49m
�[38;5;244mE/flutter (13747): #18158 Element.rebuild�[39;49m
�[38;5;244mE/flutter (13747): #18159 ComponentElement._firstBuild�[39;49m
E/flutter (13747): #18160 ComponentElement.mount (package:flutter/src/widgets/framework.dart:42

�[38;5;248m════════ Exception caught by widgets library ═══════════════════════════════════�[39;49m
�[38;5;244mThe following StackOverflowError was thrown building _DisposableWidget(state: __DisposableWidgetState#86548):�[39;49m
Stack Overflow

�[38;5;244mThe relevant error-causing widget was�[39;49m
�[38;5;248mMaterialApp�[39;49m
�[38;5;244mWhen the exception was thrown, this was the stack�[39;49m
�[38;5;244m#0 _LinkedHashMapMixin._getValueOrData (dart:collection-patch/compact_hash.dart:333:3)�[39;49m
�[38;5;244m#1 _LinkedHashMapMixin.containsKey (dart:collection-patch/compact_hash.dart:357:53)�[39;49m
�[38;5;248m#2 ChildModule.getBind�[39;49m
�[38;5;248m#3 Modular.get�[39;49m
�[38;5;248m#4 Inject.get�[39;49m
�[38;5;244m...�[39;49m
�[38;5;248m════════════════════════════════════════════════════════════════════════════════�[39;49m

[Dúvida] ModuleWidget e o dispose do Controller

Há alguma forma de evitar o dispose do Controller de um ModuleWidget?

Tenho uma ModuleWidget que uso dentro de um BottomNav,
Mesmo usando varias formas e manter a instancia, o Controller sempre é recriado
e as requisições lá são refeitas quando troco de um ModuleWidget para outro.

`class ServicesModule extends ModuleWidget {
@OverRide
List get binds => [
Bind((i) => ServicesController(i.get())),
Bind((i) => ServicesRepository()),
];

static Inject get to => Inject.of();

@OverRide
Widget get view => ServicesPage(key: PageStorageKey('service'));

}`

Sei que posso "bindar" no pai, mas achei legal dentro do ModuleWidget
Desde já obrigado!

Rotas para dialogs

Seria interessante a possibilidade de criar rotas que direcionam para dialogs, especialmente os do tipo fullscreen de acordo com a especificação do Material Design, possibilitando a criação de um módulo com ciclo de vida limitado à vida do mesmo, o que seria bem útil em casos como telas de detalhes de produto, por exemplo, entre outros.

Problema ao acessar Blocs de outros módulos

Estou com um problema ao acessar uma classe Bloc de outro módulo, não tenho certeza se é algum problema dos módulos ou alguma coisa que eu acabei esquecendo. Segue o fluxo abaixo:

Problema:
Captura de Tela 2019-12-23 às 15 04 27

Note que eu acesso o AppThemeBloc da mesma forma, mas quando tento acessar o CompanyBloc, ele não aceita. Apesar disso, o auto-complete preenche certinho o .to.get().

Só está funcionando instanciando o objeto da classe, conforme visto na linha 22 comentado.

Seguem demais prints:

Estrutura de arquivos:
Captura de Tela 2019-12-23 às 15 01 04

CompanyModule
Captura de Tela 2019-12-23 às 15 04 55

AppModule
Captura de Tela 2019-12-23 às 15 05 13

Modular.to.pop() vs Navigator.pop() inside AlertDialog close button

I have the following test case that opens and closes an AlertDialog.

testWidgets('Status should back to IDLE when INVALID dialog is closed.', (WidgetTester tester) async {
      LoginController loginController = Modular.get();

      AlertDialog dialog = await showInvalidDialog(tester, loginController);

      // Closes the dialog
      Finder dialogCloseButton = find.descendant(of: find.byType(AlertDialog), matching: find.byType(FlatButton));
      await tester.tap(dialogCloseButton);
      await tester.pump();
      

      expect(find.byType(AlertDialog), findsNothing);
      expect(loginController.loginState, equals(LoginState.IDLE));
    });

The Dialog:

class _LoginPageState extends State<LoginPage> {
  LoginController controller = Modular.get<LoginController>();
  ReactionDisposer disposer;

  @override
  void initState() {
    super.initState();
    disposer = autorun((_) {
      if(controller.loginState == LoginState.INVALID) {
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text(controller.error.formErrorMessage.invalidTitle),
            content: Text(controller.error.formErrorMessage.invalidContent),
            actions: <Widget>[
              FlatButton(
                child: Text("OK"),
                onPressed: () {
                  controller.setLoginState(LoginState.IDLE);
                  Navigator.pop(context);
                },
              )
            ],
          ),
        );
      }
    });
  }

When the AlertDialog is open, if I try to close it using Modular.to.pop() method, I get this exception during the test execution:

══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Add Modular.navigatorKey in your MaterialApp;

      return MaterialApp(
        navigatorKey: Modular.navigatorKey,
        ...

.
'package:flutter_modular/src/modular_base.dart':
Failed assertion: line 39 pos 9: '_navigatorKey != null'

When the exception was thrown, this was the stack:
#2      Modular.to (package:flutter_modular/src/modular_base.dart:39:9)

Although the exception's error message is very helpful, I already have "navigatorKey: Modular.navigatorKey" set inside MaterialApp().

The only way to get this code working is to make a replacement of Modular.to.get() by Navigator.pop(context).

Using Navigator.pop(context), the test passes Ok.

In debug mode, Modular.to.get() and Navigator.pop() have the same behaviour, with no exceptions. The error only occurs inside test cases.

Am I missing some point with Modular.to.get() usage or there's some kind of bug related to this method when used inside test cases or, particularly, inside Dialog widgets?

Thanks in advance.

Erro ao usar initModule com um ModuleWidget

Não é possível iniciar um módulo criado com --noroute (ou seja, um ModuleWidget) com initModule para testes unitários porque ModuleWidget não tem mais o mixin de ChildModule.

Agora quando tentamos dar initModule em um module que é ModuleWidget:

class NotasModule extends ModuleWidget {
  @override
  List<Bind> get binds => [
        Bind((i) => NotasController()),
      ];

  static Inject get to => Inject<NotasModule>.of();

  @override
  Widget get view => NotasPage();
}
initModule(NotasModule());

Recebemos o erro:
The argument type 'NotasModule' can't be assigned to the parameter type 'ChildModule'.

Antes funcionava normalmente, mas esse commit retirou o mixin:
4a6650f#diff-9b1991b90e70f8bf922d9f6b2358e496R4

Algum motivo específico? Podemos trazer de volta ou há outro jeito de dar initModule em um ModuleWidget?

Why Routers and not Routes?

Router = the component that manages the routes.
Route = a named path to some destination.

There is a lot of mispelled messages and concepts that would make this library weird to worldwide adoption.

Example: https://github.com/Flutterando/modular/blob/master/lib/src/inject/bind.dart:

singleton can not be false when lazy be false

Should be

singleton can not be false when lazy is false, or, better yet: 'singleton' can't be false if 'lazy' is also false

Language matters.

Singletons e Não-Sigletons

Hoje precisei implantar uma classe que nao podia ser singleton, e quando fui procurar no Bind ele nao me da essa opção de escolha assim como BlocPattern fornecia.

Como faz agora? Ou ainda não foi implementado?

Deixar o lazy loading opcional

Seria interessante no modular o lazy loading ser opcional, fazendo a classe ser instanciada assim que módulo é iniciado, resolvendo problemas como quando é preciso que uma classe seja instanciada assim que o módulo inicia, sem precisar instância lo na view.
Poderia ser algo como:

Bind((i) => AppController, lazy: false)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.