pmvvm icon indicating copy to clipboard operation
pmvvm copied to clipboard

notifyListeners does not update dialog/alertDialog

Open skast96 opened this issue 1 year ago • 3 comments

I have a password verification dialog where you have to enter the password of your app. If the password is wrong i want to diplay a errorLabel with

 errorText: viewModel.wrongPasswordReset ? "Wrong password" : null,

However, when i call notifyListeners() in my ViewModel after checking if the password was correct the dialog does not get updated to show the error message. I am using a HookView for my View if that helps.

skast96 avatar Nov 14 '22 14:11 skast96

Hi @skast96 ,

Can u please copy the full example to be able to trace the issue?

NourEldinShobier avatar Nov 14 '22 14:11 NourEldinShobier

The code below is an example on how I am using the dialog.


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

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(
        primarySwatch: Colors.blue,
      ),
      home: MyWidget(),
    );
  }
}

class MyViewModel extends ViewModel {
  int counter = 0;

  // Optional
  @override
  void init() {
    // It's called after the MVVM widget's initState is called
  }

  // Optional
  @override
  void onBuild() {
    // A callback when the `build` method of the view is called.
  }

  void increase() {
    counter++;
    notifyListeners();
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MVVM<MyViewModel>(
      view: () => _MyView(),
      viewModel: MyViewModel(),
    );
  }
}

class _MyView extends HookView<MyViewModel> {
  @override
  Widget render(context, vmodel) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Text(vmodel.counter.toString()),
        SizedBox(height: 24),
        ElevatedButton(
          onPressed: () => showDialog<String>(
              context: context,
              builder: (BuildContext context) => AlertDialog(
                    title: Text("Inc"),
                    content: TextField(
                      obscureText: true,
                      decoration: InputDecoration(
                          border: OutlineInputBorder(),
                          errorText:
                              vmodel.counter % 2 == 0 ? "Counter is odd" : null,
                          labelText: vmodel.counter.toString()),
                    ),
                    actions: <Widget>[
                      TextButton(
                          onPressed: () => Navigator.pop(context, 'Cancel'),
                          child: Text("Cancel")),
                      TextButton(
                          onPressed: vmodel.increase, child: Text("Increase")),
                    ],
                  )),
          child: Text("Increase"),
        ),
      ],
    );
  }
}

skast96 avatar Nov 15 '22 08:11 skast96

I found a solution but I do not know if that is the correct way. I am using a StatefulBuilder around the AlertDialog.

return showDialog<String>(
        barrierDismissible: false,
        context: vmodel.context,
        builder: (BuildContext context) => StatefulBuilder(
                builder: (BuildContext context, StateSetter setState) {
              return AlertDialog(
                title: Text("Inc"),
                content: TextField(
                  obscureText: true,
                  decoration: InputDecoration(
                      border: OutlineInputBorder(),
                      errorText:
                          vmodel.counter % 2 == 0 ? "Counter is odd" : null,
                      labelText: vmodel.counter.toString()),
                ),
                actions: <Widget>[
                  TextButton(
                      onPressed: () => Navigator.pop(context, 'Cancel'),
                      child: Text("Cancel")),
                  TextButton(
                      onPressed: () => {
                            setState(() => {vmodel.increase()})
                          },
                      child: Text("Increase")),
                ],
              );
            }));

skast96 avatar Nov 15 '22 09:11 skast96