DaveRGP
DaveRGP

Reputation: 1480

Why does this FAB not update the state?

I have followed as best I can this question: Adding new ListTile item on click

Though it is not necessarily as reproducible as it could be, I've created something that compiles, but does not run as expected:

import 'package:flutter/material.dart';

void main() => runApp(SeedBank());

class SeedBank extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Colors.lightGreen,
      ),
      home: Seeds(),
    );
  }
}

class Seeds extends StatefulWidget {
  @override
  SeedsState createState() => SeedsState();
}

class SeedsState extends State<Seeds> {
  var _seedSection = List<Widget>();

  Card seedSectionMethod(String title, String subtitle) {
    return new Card(
      child: ListTile(
          title: Text(
            title,
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          subtitle: Text(subtitle),
          trailing: Icon(Icons.more_vert)),
    );
  }

  void initState() {
    super.initState();
    _seedSection.add(
      seedSectionMethod("Leek", "Bulgaarse Reuzen - Lincoln"),
    );
    _seedSection.add(
      seedSectionMethod("Kale", "Jardin mix"),
    );
    _seedSection.add(
      seedSectionMethod("Sunflower", "Helianthus Red"),
    );
  }

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Seed Bank'),
      ),
      body: ListView(
        children: this._seedSection,
      ),
      floatingActionButton: FloatingActionButton(
        child: Text("+"),
        onPressed: () {
          setState(() {
            _seedSection.add(
              seedSectionMethod("New Seed", "With notes"),
            );
          });
        },
        backgroundColor: Colors.lightGreenAccent,
      ),
    );
  }
}

The desired behaviour is:

I expect I have missed something basic in flutter about setting state (only started yesterday), but I'm in a rut about where to go next to understand it more.

V2:

using @andrea689, I can compile, but have hit the same problem again:

class SeedsState extends State<Seeds> {
  var _seedSection = List<Widget>();

  var _seeds = [
    ["Leek", "Bulgaarse Reuzen - Lincoln"],
    ["Kale", "Jardin mix"],
    ["Sunflower", "Helianthus Red"],
  ];

  Card seedSectionMethod(String title, String subtitle) {
    return new Card(
      child: ListTile(
          title: Text(
            title,
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          subtitle: Text(subtitle),
          trailing: Icon(Icons.more_vert)),
    );
  }

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Seed Bank'),
      ),
      body:  ListView.builder(
        itemCount: _seedSection.length,
        itemBuilder: (context, index) {
          return seedSectionMethod(_seeds[index][0], _seeds[index][1]);
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Text("+"),
        onPressed: () {
          setState(() {
            _seeds.add(["New Seed", "With notes"]);
          });
        },
        backgroundColor: Colors.lightGreenAccent,
      ),
    );
  }
}

Is this how the class is supposed to look? It's now not adding a new item again.

Final Solution

import 'package:flutter/material.dart';

void main() => runApp(SeedBank());

class SeedBank extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Colors.lightGreen,
      ),
      home: Seeds(),
    );
  }
}

class Seeds extends StatefulWidget {
  @override
  SeedsState createState() => SeedsState();
}

class SeedsState extends State<Seeds> {
  var _seeds = [
    ["Leek", "Bulgaarse Reuzen - Lincoln"],
    ["Kale", "Jardin mix"],
    ["Sunflower", "Helianthus Red"],
  ];

  Card seedSectionMethod(String title, String subtitle) {
    return new Card(
      child: ListTile(
          title: Text(
            title,
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          subtitle: Text(subtitle),
          trailing: Icon(Icons.more_vert)),
    );
  }

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Seed Bank'),
      ),
      body: ListView.builder(
        itemCount: _seeds.length,
        itemBuilder: (context, index) {
          return seedSectionMethod(_seeds[index][0], _seeds[index][1]);
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Text("+"),
        onPressed: () {
          setState(() {
            setState(() {
              _seeds.add(["New Seed", "With notes"]);
            });
          });
        },
        backgroundColor: Colors.lightGreenAccent,
      ),
    );
  }
}

Upvotes: 0

Views: 76

Answers (3)

andrea689
andrea689

Reputation: 684

Since _seedSection is modified, you have to use ListView.builder

ListView.builder(
     itemCount: _seedSection.length,
     itemBuilder: (context, index) {
          return _seedSection[index];
     },
),

Moreover, it is better to store in state only the values and make the widget inside itemBuilder.

var _seeds = [
    ["Leek", "Bulgaarse Reuzen - Lincoln"],
    ["Kale", "Jardin mix"],
    ["Sunflower", "Helianthus Red"],
  ];

ListView.builder(
     itemCount: _seeds.length,
     itemBuilder: (context, index) {
          return seedSectionMethod(_seeds[index][0], _seeds[index][1]);
     },
),

setState(() {
     _seeds.add(["New Seed", "With notes"]);
});

Upvotes: 2

Piyush Jain
Piyush Jain

Reputation: 1986

try like this.

body: ListView.builder(
  itemCount: this._seedSection.length,
  itemBuilder: (context, index) => this._seedSection[index],
),

Here is working demo. https://dartpad.dev/43a5b08327ed0f64fd084947873a3e52

Upvotes: 2

Will Hlas
Will Hlas

Reputation: 1351

Try adding this:

body: ListView(
  children: this._seedSection.map((data) {
    return data;
  }).toList(),
),

Upvotes: 1

Related Questions