flutter-elementary icon indicating copy to clipboard operation
flutter-elementary copied to clipboard

Passing wm inside child widgets?

Open Tamerlanchiques opened this issue 1 year ago • 6 comments

I have ElementaryWidget that contains Scaffold inside it and I decided to spread Scaffold into AppBar, Body and Bottom classes like this:


< some  other imports … >

part 'widgets/chat_page_app_bar.dart';
part 'widgets/chat_page_body.dart';
part 'widgets/chat_page_bottom_bar.dart';

class ChatPageWidget extends ElementaryWidget<IChatPageWidgetModel> {
  final String title;

  const ChatPageWidget({
    Key? key,
    this.title = 'Чат с диспетчером',
    WidgetModelFactory wmFactory = defaultChatPageWidgetModelFactory,
  }) : super(wmFactory, key: key);

  @override
  Widget build(IChatPageWidgetModel wm) {
    return GestureDetector(
        onTap: wm.onTapOutsideMessageTextField,
        child: Scaffold(
          resizeToAvoidBottomInset: true,
          appBar: ChatPageAppBar(title: title),
          body: Column(
            children: [
              Expanded(
                  child: ChatPageBody(
                wmFactory,
              )),
              ChatPageBottomBar(wmFactory)
            ],
          ),
        ));
  }
}

These parts extends Elementary Widget<IChat Page Widget Model> as well. Of course, I faced with issue when new Widget Model instance creates each time instead of using the same instance created in parent ChatPageWidget. I could convert parts to simple Stateless widgets and pass wm variable in their constructors but in this case I have access to context leaks to its build method that breaking single source of truth of WidgetModel.

Is there way to keep AppBar, Body and BottomBar widgets as ElementaryWidgets with build(IChatPageWidgetModel wm) function instead of build(BuildContext context) one?

Tamerlanchiques avatar May 29 '24 23:05 Tamerlanchiques

@Tamerlanchiques Привет, а точно ли нужно их связывать? Может правильнее чтоб каждый виджет владел той информацией которая ему нужна, а не всей моделью экрана?

vlkonoshenko avatar Jun 11 '24 20:06 vlkonoshenko

@vlkonoshenko Привет.

Хм. По идее, да. Можно для каждой части Scaffold'a сделать свою вью-модель.

Получить связки вида ChatPageAppBarWidget – ChatPageAppBarWidgetModel, ChatPageBodyWidget – ChatPageBodyWidgetModel и ChatPageBottomWidget – ChatPageBottomWidgetModel и управлять этим одной моделью ChatPageModel.

Правда, вижу тут местами момент с дубликацией кода. Например, я хочу слушать из Model слоя стрим переменной «можно/нельзя писать в чате» и в Body хочу написать заглушку, «вы не можете писать в чате…» и, при этом, заблокировать возможность писать сообщения и нажимать кнопку «отправить» в Bottom. Получается, нужно будет делать логику управления подпиской и в BodyWidgetModel и в BottomWidgetModel. Но, может быть, это не так страшно и зато всё будет лучше упорядочено по полочкам. В Body будет всё необходимое для Body, в Bottom всё необходимое для Bottom.

Tamerlanchiques avatar Jun 11 '24 21:06 Tamerlanchiques

Привет. Ну тут вроде бы все логично - если снизу идет связка работающая по паттерну MVVM, то для нее будет своя WM, своя модель. Если ниже будет только использоваться выше лежащая WM то не надо создавать новую связку MVVM, и просто нижележащий виджет сделать Stateless/Stateful и передать ему как зависимость саму WM, или требуемые свойства (в зависимости от того как больше нравится).

MbIXjkee avatar Jun 23 '24 13:06 MbIXjkee

Привет. Действительно, вариант сделать нижестоящие Stateless/ful виджеты с передачей зависимости логична, но меня просто триггерит открывающийся в таком случае доступ к контексту :). В целом, ничего страшного. Получается, чтобы довести до абсолюта, то реально нужно будет ещё несколько MVVM для разных частей страницы, что выглядит уже слишком избыточным…

Tamerlanchiques avatar Jun 27 '24 20:06 Tamerlanchiques

А для нижележащих это нормально, ты же там в результате все равно используешь базовые виджеты - кнопки, переключатиели. Так они через него к теме ходят и тд. Это все ок, я например темминг и локализацию сам предпочту не заморачиваться через WM, а сделать как обычно. Это все будет отлично работать. Отданный WM контекст это в самой связке MVVM имеет смысл, своеобразная защита от того чтобы не размазывали логику куда не предполагалось. И прям упарываться в то чтобы на каждый чих создавать MVVM связку, на мой взгляд не надо. Инструмент должен помогать, а не мешать.

MbIXjkee avatar Jun 28 '24 17:06 MbIXjkee

Ну и контекст там скрыт же только формально - всегда можно все в билдер обернуть и все, "защита" пройдена. Точно так же как (BuildContext as Element) в Stateless или Stateful сделать, и все - вот доступ к "скрытым" методам.

MbIXjkee avatar Jun 28 '24 17:06 MbIXjkee