Dendimuhmd
Dendimuhmd

Reputation: 83

How to use Function callback if i'm use to change state with new val on Switch widget?

i tried to change new state with Switch widget but it can't be used, in case i create dynamic function and will to used in widget tree's, in function i send callback function at parameter for Switch widget, but in actual it is cannot be used.

code base

import 'package:flutter/material.dart';
import 'package:navigate_app/widgets/main_drawer.dart';

class FilterScreen extends StatefulWidget {
  static const routeNamed = '/filter';

  @override
  State<FilterScreen> createState() => _FilterScreenState();
}

class _FilterScreenState extends State<FilterScreen> {
  bool _glutenFree = false;
  bool _vegetarian = false;
  bool _vegan = false;
  bool _lactoseFree = false;

  Widget _buildSwitchFilter(String title, String description, bool currentValue,
      Function updateValue) {
    return SwitchListTile(
        title: Text(title),
        subtitle: Text(description),
        value: currentValue,
        onChanged: (val) => updateValue);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        drawer: MainDrawer(),
        appBar: AppBar(),
        body: Column(
          children: [
            Expanded(
                child: ListView(
              children: [
                _buildSwitchFilter('Gluten-free',
                    'Only include gluten-free meals', _glutenFree, (newVal) {
                  setState(() {
                    _glutenFree == newVal;
                  });
                }),
                _buildSwitchFilter(
                    'Lactose-free',
                    'Only include lactose-free meals',
                    _glutenFree,
                    (newVal) => _lactoseFree == newVal),
                _buildSwitchFilter(
                    'Vegan-free',
                    'Only include vegan-free meals',
                    _glutenFree,
                    (newVal) => _vegan == newVal),
                _buildSwitchFilter(
                    'Vegetarian-free',
                    'Only include vegetarian-free meals',
                    _glutenFree,
                    (newVal) => _vegetarian == newVal),
              ],
            ))
          ],
        ));
  }
}

it's pict

Upvotes: 3

Views: 1943

Answers (6)

Ryan Soo
Ryan Soo

Reputation: 1

In addition to these corrections, you need to use the correct boolean variables (_vegetarian, _vegan, _lactoseFree) for each of your _buildSwitchFilter widgets. Also, it should be "vegan", not "vegan-free".

Upvotes: 0

Dmitry Rodionov
Dmitry Rodionov

Reputation: 363

Here in code are 4 problems:

  1. You need to use "=" operator instead of "==" (_glutenFree = newVal instead of _glutenFree == newVal)

  2. You need to pass to the _buildSwitchFilter() - "Function(bool) updateValue" as an argument, and use "onChanged: updateValue":

    Widget _buildSwitchFilter(String title, String description, bool currentValue,
          Function(bool) updateValue) {
        return SwitchListTile(
           title: Text(title),
           subtitle: Text(description),
           value: currentValue,
           onChanged: updateValue);
      }
    
  3. You passing everywhere _glutenFree as third argument in _buildSwitchFilter(), but you need to pass:

_glutenFree;

_lactoseFree;

_vegan;

_vegetarian;

  1. You pass function with setState(){} only first time, You need to do it in all _buildSwitchFilter().

Here is the solution:

    import 'package:flutter/material.dart';
    import 'package:navigate_app/widgets/main_drawer.dart';
    
    class FilterScreen extends StatefulWidget {
      static const routeNamed = '/filter';
    
      @override
      State<FilterScreen> createState() => _FilterScreenState();
    }
    
    class _FilterScreenState extends State<FilterScreen> {
      bool _glutenFree = false;
      bool _vegetarian = false;
      bool _vegan = false;
      bool _lactoseFree = false;
    
    Widget _buildSwitchFilter(String title, String description, bool currentValue,
          Function(bool) updateValue) {
        return SwitchListTile(
            title: Text(title),
            subtitle: Text(description),
            value: currentValue,
            onChanged: updateValue);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            drawer: MainDrawer(),
            appBar: AppBar(),
            body: Column(
              children: [
                Expanded(
                    child: ListView(
                      children: [
                        _buildSwitchFilter('Gluten-free',
                            'Only include gluten-free meals', _glutenFree, (newVal) {
                              setState(() {
                                _glutenFree = newVal;
                              });
                            }),
                        _buildSwitchFilter(
                            'Lactose-free',
                            'Only include lactose-free meals',
                            _lactoseFree,
                                (newVal) {
                                  setState(() {
                                    _lactoseFree = newVal;
                                  });
                                }),
                        _buildSwitchFilter(
                            'Vegan-free',
                            'Only include vegan-free meals',
                            _vegan,
                                (newVal) {
                              setState(() {
                                _vegan = newVal;
                              });
                            }),
                        _buildSwitchFilter(
                            'Vegetarian-free',
                            'Only include vegetarian-free meals',
                            _vegetarian,
                                (newVal) {
                              setState(() {
                                _vegetarian = newVal;
                              });
                            }),
                      ],
                    ))
              ],
            ));
      }
    }

Upvotes: 0

DiyorbekDev
DiyorbekDev

Reputation: 774

import 'package:flutter/material.dart';
import 'package:navigate_app/widgets/main_drawer.dart';

class FilterScreen extends StatefulWidget {
  static const routeNamed = '/filter';

  @override
  State<FilterScreen> createState() => _FilterScreenState();
}

class _FilterScreenState extends State<FilterScreen> {
  bool _glutenFree = false;
  bool _vegetarian = false;
  bool _vegan = false;
  bool _lactoseFree = false;

  Widget _buildSwitchFilter(String title, String description, bool currentValue,
      Function(bool) updateValue) {
    return SwitchListTile(
        title: Text(title),
        subtitle: Text(description),
        value: currentValue,
        onChanged: (val) => updateValue);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        drawer: MainDrawer(),
        appBar: AppBar(),
        body: Column(
          children: [
            Expanded(
                child: ListView(
              children: [
                _buildSwitchFilter('Gluten-free',
                    'Only include gluten-free meals', _glutenFree, (newVal) {
                  setState(() {
                    _glutenFree = newVal;
                  });
                }),
                _buildSwitchFilter(
                    'Lactose-free',
                    'Only include lactose-free meals',
                    _lactoseFree,
                    (newVal) {
                      setState(() {
                    _lactoseFree = newVal;
                  });
                    } ),
                _buildSwitchFilter(
                    'Vegan-free',
                    'Only include vegan-free meals',
                    _vegan,
                    (newVal)  {
                      setState(() {
                    _vegan = newVal;
                  });
                    } ),
                _buildSwitchFilter(
                    'Vegetarian-free',
                    'Only include vegetarian-free meals',
                    _vegetarian,
                    (newVal) {
                       setState(() {
                    _vegetarian = newVal;
                  });
                    } ),
              ],
            ))
          ],
        ));
  }
}

Upvotes: 1

Shirsh Shukla
Shirsh Shukla

Reputation: 5973

== is a method operator

basically is an equality operator. The default behavior for all Objects is to return true if and only if this and others are the same object. Override this method to specify a different equality relation on a class.

        _buildSwitchFilter('Gluten-free',
            'Only include gluten-free meals', _glutenFree, (newVal) {
          setState(() {
            _glutenFree == newVal;
          });
        }),

basically this line work as conditional operator _glutenFree == newVal;

So, if you want to assign any value to any variable like as you want to assign `_glutenFree = false/true

So, on that condition, you should use the assignment operator "="

like right way is,

  _glutenFree = newVal;

Upvotes: 2

jamieastley
jamieastley

Reputation: 610

There are several reasons why this isn't working:

  1. Not actually invoking your callback or passing the value:
    Widget _buildSwitchFilter(
      String title,
      String description, 
      bool currentValue,
      Function updateValue,
    ) {
    return SwitchListTile(
        title: Text(title),
        subtitle: Text(description),
        value: currentValue,
        onChanged: (val) => updateValue);
    }

Should instead be:

    Widget _buildSwitchFilter(
      String title,
      String description, 
      bool currentValue,
      Function(bool value) updateValue, // <- note the return value
    ) {
    return SwitchListTile(
        title: Text(title),
        subtitle: Text(description),
        value: currentValue,
        onChanged: (val) => updateValue(val)); // <- passing the `val` to your callback
    }
  1. Copypasta'd ListView children. Each _buildSwitchFilter() should have the related state value as to what they're for, but each uses _glutenFree as their state value.

  2. 3 out of 4 switches aren't calling setState() when their callback is triggered.

  3. You're not updating local state values, you're comparing equality.

setState(() {
  _glutenFree == newVal;
});

Should be:

setState(() {
  _glutenFree = newVal;
});

Upvotes: 3

Mozes Ong
Mozes Ong

Reputation: 1294

This is incorrect

_glutenFree == newVal;

== is an equality operator https://api.dart.dev/be/137051/dart-core/Object/operator_equals.html

What u need is to assign the value using =

Correct:

_glutenFree = newVal;

Do the same for the others

Upvotes: 7

Related Questions