1
votes

I'm trying to create an authentication andoid APP using Flutter Dark. I've created a node js server with endpoint API for the login signup route which directly communicates with the Atlas MongoDB database. I can successfully send POST request in POSTMAN but when I try to call it from inside the flutter app I get an error as below

Restarted application in 3,634ms. I/flutter (10513): TextFormField I/flutter (10513): TextFormField E/flutter (10513): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: type 'TextFormField' is not a subtype of type 'String' [38;5;248mE/flutter (10513): #0 login[39;49m package:cop_app/login_page.dart [38;5;248mE/flutter (10513): #1 LoginSection.build.[39;49m package:cop_app/login_page.dart [38;5;248mE/flutter (10513): #2 LoginSection.build.[39;49m package:cop_app/login_page.dart [38;5;244mE/flutter (10513): #3
_InkResponseState._handleTap[39;49m package:flutter/…/material/ink_well.dart [38;5;244mE/flutter (10513): #4 GestureRecognizer.invokeCallback[39;49m package:flutter/…/gestures/recognizer.dart [38;5;244mE/flutter (10513): #5 TapGestureRecognizer.handleTapUp[39;49m package:flutter/…/gestures/tap.dart [38;5;244mE/flutter (10513): #6
BaseTapGestureRecognizer._checkUp[39;49m package:flutter/…/gestures/tap.dart [38;5;244mE/flutter (10513): #7
BaseTapGestureRecognizer.acceptGesture[39;49m package:flutter/…/gestures/tap.dart [38;5;244mE/flutter (10513): #8
GestureArenaManager.sweep[39;49m package:flutter/…/gestures/arena.dart [38;5;244mE/flutter (10513): #9 GestureBinding.handleEvent[39;49m package:flutter/…/gestures/binding.dart [38;5;244mE/flutter (10513): #10 GestureBinding.dispatchEvent[39;49m package:flutter/…/gestures/binding.dart [38;5;244mE/flutter (10513): #11 RendererBinding.dispatchEvent[39;49m package:flutter/…/rendering/binding.dart [38;5;244mE/flutter (10513): #12 GestureBinding._handlePointerEventImmediately[39;49m package:flutter/…/gestures/binding.dart [38;5;244mE/flutter (10513): #13 GestureBinding.handlePointerEvent[39;49m package:flutter/…/gestures/binding.dart [38;5;244mE/flutter (10513): #14 GestureBinding._flushPointerEventQueue[39;49m package:flutter/…/gestures/binding.dart [38;5;244mE/flutter (10513): #15 GestureBinding._handlePointerDataPacket[39;49m package:flutter/…/gestures/binding.dart [38;5;244mE/flutter (10513): #16 _rootRunUnary (dart:async/zone.dart:1370:13)[39;49m [38;5;244mE/flutter (10513): #17 _CustomZone.runUnary (dart:async/zone.dart:1265:19)[39;49m [38;5;244mE/flutter (10513): #18 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)[39;49m [38;5;244mE/flutter (10513): #19 _invoke1 (dart:ui/hooks.dart:180:10)[39;49m [38;5;244mE/flutter (10513): #20
PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:276:7)[39;49m [38;5;244mE/flutter (10513): #21 _dispatchPointerDataPacket (dart:ui/hooks.dart:96:31)[39;49m E/flutter (10513):

here is my code

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'profile.dart';

class LoginSection extends StatelessWidget {
  static const String id = "LoginSection";
  var uid;
  var password;
  @override
  Widget build(BuildContext context) {
    final logo = Hero(
      tag: 'hero',
      child: CircleAvatar(
        backgroundColor: Colors.transparent,
        radius: 48.0,
        child: Image.asset('assets/profile.png'),
      ),
    );

    final uid = TextFormField(
      textAlign: TextAlign.center,
      keyboardType: TextInputType.text,
      autofocus: false,
      initialValue: 'abc123',
      decoration: InputDecoration(
        hintText: 'Unique ID',
        contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
        border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
      ),
    );

    final password = TextFormField(
      textAlign: TextAlign.center,
      autofocus: false,
      initialValue: '123abc',
      obscureText: true,
      decoration: InputDecoration(
        hintText: 'Password',
        contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
        border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
      ),
    );

    final loginButton = Padding(
      padding: EdgeInsets.symmetric(vertical: 16.0),
      child: RaisedButton(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(24),
        ),
        onPressed: () async {
          await login(uid, password);
          SharedPreferences prefs = await SharedPreferences.getInstance();
          String token = prefs.getString("token");
          print(token);
          if (token != null) {
            Navigator.popAndPushNamed(context, LandingScreen.id);
          }
        },
        padding: EdgeInsets.all(12),
        color: Colors.lightBlueAccent,
        child: Text('Log In', style: TextStyle(color: Colors.white)),
      ),
    );

    final forgotLabel = FlatButton(
      child: Text(
        'Forgot password?',
        style: TextStyle(color: Colors.black54),
      ),
      onPressed: () {},
    );
    return Scaffold(
      backgroundColor: Colors.white,
      body: Center(
        child: ListView(
          shrinkWrap: true,
          padding: EdgeInsets.only(left: 24.0, right: 24.0),
          children: <Widget>[
            logo,
            SizedBox(height: 48.0),
            uid,
            SizedBox(height: 8.0),
            password,
            SizedBox(height: 24.0),
            loginButton,
            forgotLabel
          ],
        ),
      ),
    );
  }
}

login(uid, password) async {
  print(uid);
  print(password);
  var url = "http://192.147.111.104:5000/login"; // iOS
  final http.Response response = await http.post(
    url,
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: jsonEncode(<String, String>{
      'uid': uid,
      'password': password,
    }),
  );
  print(response.body);
  SharedPreferences prefs = await SharedPreferences.getInstance();
  var parse = jsonDecode(response.body);

  await prefs.setString('token', parse["token"]);
}

I can't understand the problem here I referred to this source for a code snippet for sending post request https://flutter.dev/docs/cookbook/networking/send-data I searched for similar issues but couldn't find any solution related to my problem can anyone help me fix this problem ?

2

2 Answers

0
votes

TextFormField is a widget used in forms to gather user input.

https://api.flutter.dev/flutter/material/TextFormField-class.html

The TextEditingController passed into the widget as an argument is how you can access user input.

https://api.flutter.dev/flutter/widgets/TextEditingController-class.html

In your case where you do your post request, you will want to access the controller.text instead of passing in the entire widget.


class VeryBasicForm extends StatefulWidget {
  @override
  _VeryBasicFormState createState() => _VeryBasicFormState();
}

class _VeryBasicFormState extends State<VeryBasicForm> {
  final uidController = TextEditingController();
  final passwordController = TextEditingController();
  @override
  void initState(){
  // set initial value here
  uidController.text = 'abc123';
  passwordController.text = 'abc123';
    super.initState();
  }

  @override
  void dispose() {
    uidController.dispose();
    passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextFormField(
          textAlign: TextAlign.center,
          controller: uidController,
          keyboardType: TextInputType.text,
          autofocus: false,
          decoration: InputDecoration(
            hintText: 'Unique ID',
            contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
          ),
        ),
        TextFormField(
          textAlign: TextAlign.center,
          controller: passwordController,
          autofocus: false,
          obscureText: true,
          decoration: InputDecoration(
            hintText: 'Password',
            contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
          ),
        ),
        Padding(
          padding: EdgeInsets.symmetric(vertical: 16.0),
          child: RaisedButton(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(24),
            ),
            onPressed: () async {
              // pass in the String values from inputs using the controllers
              await login(uidController.text, passwordController.text);
              SharedPreferences prefs = await SharedPreferences.getInstance();
              String token = prefs.getString("token");
              print(token);
              if (token != null) {
                Navigator.popAndPushNamed(context, LandingScreen.id);
              }
            },
            padding: EdgeInsets.all(12),
            color: Colors.lightBlueAccent,
            child: Text('Log In', style: TextStyle(color: Colors.white)),
          ),
        );
      ],
    );
  }
}
0
votes

You are passing a TextFormField widget to what I presume you wanted to be text. Define a controller first like this,

final myPasswordController = TextEditingController();
final myUIDController = TextEditingController();

Then use it in you functions like

final password = TextFormField(
  textAlign: TextAlign.center,
  controller: myPassWordController,
  autofocus: false,
  obscureText: true,
  decoration: InputDecoration(
    hintText: 'Password',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
    border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
  ),
);

final uid = TextFormField(
  textAlign: TextAlign.center,
  controller: myUIDController,
  keyboardType: TextInputType.text,
  autofocus: false,
  decoration: InputDecoration(
    hintText: 'Unique ID',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
    border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
  ),
);

Then in you onpressed;

         await login(myPasswordController.text, myPasswordController.text);