Search code examples
flutterflutter-dependenciesflutter-webflutter-test

Expected a value of type 'String', but got one of type 'Null'


I have to add new product as well as edit existing product in one screen . so I have Used didchangedependencies method by assigning the initial values to update a screen something gone wrong in my code.please help me out. so the error is enter image description here

Error is showing here:

@override
      void didChangeDependencies() {
        if (_isinit) {
          final productId = ModalRoute.of(context)!.settings.arguments as String;

      // ignore: unnecessary_null_comparison
      if (productId != null) {
        _editedproduct =
            Provider.of<Products>(context, listen: false).FindByID(productId);
        _imageUrlController.text = _editedproduct.imageUrl;
        _initValues = {
          'title': _editedproduct.title,
          'description': _editedproduct.description,
          'Price': _editedproduct.price.toString(),
          // 'imageUrl': _editedproduct.imageUrl,
          'imageUrl': '',
        };
      }
    }
    _isinit = false;
    super.didChangeDependencies();
  } 

In did change dependencies method I have tried to get the arguments i.e product ID from one page but it showing null. this is screenshot where i have pushed to edit screen product page with arguments which I was tried to fetch this arguments.
enter image description here
and this is for pushing to adding product page enter image description here

import 'dart:html';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shoppingapp/Providers/Product.dart';
import 'package:shoppingapp/Providers/Products.dart';

class EditProductScreen extends StatefulWidget {
  static const routeName = '/edit-products';
  @override
  _EditProductScreenState createState() => _EditProductScreenState();
}

class _EditProductScreenState extends State<EditProductScreen> {
  final _priceFocusNode = FocusNode();
  final _descriptionFocusNode = FocusNode();
  final _imageUrlController = TextEditingController();
  final _imageUrlFocusNode = FocusNode();
  final _form = GlobalKey<FormState>();
  var _editedproduct =
      Product(id: '', title: '', description: '', price: 0, imageUrl: '');
  var _isinit = true;

  var _initValues = {
    'title': '',
    'description': '',
    'price': '',
    'imageUrl': '',
  };
  @override
  void initState() {
    _imageUrlFocusNode.addListener(_updateImageUrl);
    super.initState();
  }

  @override
  void didChangeDependencies() {
    if (_isinit) {
      final productId = ModalRoute.of(context)!.settings.arguments as String;

      // ignore: unnecessary_null_comparison
      if (productId != null) {
        _editedproduct =
            Provider.of<Products>(context, listen: false).FindByID(productId);
        _imageUrlController.text = _editedproduct.imageUrl;
        _initValues = {
          'title': _editedproduct.title,
          'description': _editedproduct.description,
          'Price': _editedproduct.price.toString(),
          // 'imageUrl': _editedproduct.imageUrl,
          'imageUrl': '',
        };
      }
    }
    _isinit = false;
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    _imageUrlFocusNode.removeListener(_updateImageUrl);
    _priceFocusNode.dispose();
    _descriptionFocusNode.dispose();
    _imageUrlFocusNode.dispose();

    super.dispose();
  }

  void _updateImageUrl() {
    if (!_imageUrlFocusNode.hasFocus) {
      setState(() {});
    }
  }

  void _saveForm() {
    final isValid = _form.currentState!.validate();
    if (isValid) {
      return;
    }
    _form.currentState!.save();
    if (_editedproduct.id != null) {
      Provider.of<Products>(context, listen: false)
          .updateProducts(_editedproduct.id, _editedproduct);
    } else {
      Provider.of<Products>(context, listen: false).addProducts(_editedproduct);
    }

    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Product'),
        actions: [
          IconButton(
            icon: Icon(Icons.save),
            onPressed: _saveForm,
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(15.0),
        child: Form(
          key: _form,
          child: ListView(
            children: [
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Title',
                ),
                initialValue: _initValues['title'],
                textInputAction: TextInputAction.next,
                validator: (value) {
                  if (value!.isEmpty) {
                    return 'Please provide a value.';
                  }
                  return null;
                },
                onFieldSubmitted: (_) {
                  FocusScope.of(context).requestFocus(_priceFocusNode);
                },
                onSaved: (value) {
                  _editedproduct = Product(
                      title: value as String,
                      price: _editedproduct.price,
                      description: _editedproduct.description,
                      imageUrl: _editedproduct.imageUrl,
                      id: _editedproduct.id,
                      isFavourite: _editedproduct.isFavourite);
                },
              ),
              TextFormField(
                initialValue: _initValues['price'],
                decoration: InputDecoration(
                  labelText: 'Price',
                ),
                textInputAction: TextInputAction.next,
                keyboardType: TextInputType.number,
                focusNode: _priceFocusNode,
                validator: (value) {
                  if (value!.isEmpty) {
                    return 'Please enter a  price ';
                  }
                  if (double.tryParse(value) == null) {
                    return 'Please Enter a Valid Number';
                  }
                  if (double.parse(value) <= 0) {
                    return 'Please Enter the number greather no than zero';
                  }
                },
                onSaved: (value) {
                  _editedproduct = Product(
                      title: _editedproduct.title,
                      price: double.parse(value!),
                      description: _editedproduct.description,
                      imageUrl: _editedproduct.imageUrl,
                      id: _editedproduct.id,
                      isFavourite: _editedproduct.isFavourite);
                },
              ),
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Description',
                ),
                initialValue: _initValues['description'],
                maxLines: 3,
                textInputAction: TextInputAction.next,
                keyboardType: TextInputType.multiline,
                focusNode: _descriptionFocusNode,
                validator: (value) {
                  if (value!.isEmpty) {
                    return 'Please enter a  description ';
                  }
                  if (value.length < 10) {
                    return 'Should be at least 10 characters long.';
                  }
                  return null;
                },
                onSaved: (value) {
                  _editedproduct = Product(
                      title: _editedproduct.title,
                      price: _editedproduct.price,
                      description: value as String,
                      imageUrl: _editedproduct.imageUrl,
                      id: _editedproduct.id,
                      isFavourite: _editedproduct.isFavourite);
                },
              ),
              Row(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Container(
                    width: 100,
                    height: 100,
                    margin: EdgeInsets.only(top: 8, right: 10),
                    decoration: BoxDecoration(
                        border: Border.all(width: 1, color: Colors.grey)),
                    child: _imageUrlController.text.isEmpty
                        ? Text('Enter a URL')
                        : FittedBox(
                            child: Image.network(
                              _imageUrlController.text,
                              fit: BoxFit.cover,
                            ),
                          ),
                  ),
                  Expanded(
                    child: TextFormField(
                      decoration: InputDecoration(labelText: 'Image URl'),
                      keyboardType: TextInputType.url,
                      textInputAction: TextInputAction.done,
                      controller: _imageUrlController,
                      focusNode: _imageUrlFocusNode,
                      validator: (value) {
                        if (value!.isEmpty) {
                          return 'Please enter a  URL ';
                        }
                        if (!value.startsWith('http') &&
                            !value.startsWith('https')) {
                          return 'Please Enter a valid URL';
                        }
                        if (!value.endsWith('.png') &&
                            !value.endsWith('.jpg') &&
                            !value.endsWith('.jpeg')) {
                          return 'Please enter a valid image URL';
                        }
                        return null;
                      },
                      onFieldSubmitted: (_) {
                        _saveForm();
                      },
                      onSaved: (value) {
                        _editedproduct = Product(
                            title: _editedproduct.title,
                            price: _editedproduct.price,
                            description: _editedproduct.description,
                            imageUrl: value as String,
                            id: _editedproduct.id,
                            isFavourite: _editedproduct.isFavourite);
                      },
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Solution

  • While Null-Safety is implemented, most tutorials were made before it so in your case where you are trying to check if the ModalRoute returns you a null value or not and do stuff depending on that, good old if(productId == null) won't work now. Instead you can do this:

    final productId = ModalRoute.of(context)!.settings.arguments == null ? "NULL":ModalRoute.of(context)!.settings.arguments as String;
    
    if(productId != "NULL"){
     
       //Do stuff here
    
    }
    

    If ModalRoute gives you null, you assign the string "NULL" to your variable productId else you just assign whatever value it returned.

    Then you can simply check if the value of productId is NULL and proceed accordingly.