Flutter composition with lots of parameter to constructor

Viewed 168

Here is the code which uses flutter composition. I have two classes Input and EmailInputField. EmailInputField returns Input with those lots of parameters. Since the parameters are declared in Input and EmailInputField both, isn't there any way to declare them in only one of them, or something simpler? Also, If I want to create another class as PasswordInputField, I will have to repeat this again. Please suggest some cleaner concept to do this.

import 'package:flutter/material.dart';
import 'package:argon_flutter/constants/Theme.dart';
import 'package:argon_flutter/validations/validators.dart';

class Input extends StatelessWidget {
  final String placeholder;
  final Widget suffixIcon;
  final Widget prefixIcon;
  final Function onTap;
  final Function onChanged;
  final TextEditingController controller;
  final bool autofocus;
  final Color borderColor;
  final bool obscureText;
  final InputDecoration decoration;
  final Function(String) validator;

  Input({
    this.placeholder,
    this.suffixIcon,
    this.prefixIcon,
    this.onTap,
    this.onChanged,
    this.autofocus = false,
    this.borderColor = ArgonColors.border,
    this.obscureText = false,
    this.decoration,
    this.controller,
    this.validator,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      child: TextFormField(
        cursorColor: ArgonColors.muted,
        cursorHeight: 14,
        onTap: onTap,
        onChanged: onChanged,
        controller: controller,
        autofocus: autofocus,
        obscureText: obscureText ? obscureText : false,
        validator: validator,
        // style: TextStyle(backgroundColor: ArgonColors.themeColor),
        // textAlignVertical: TextAlignVertical(y: 0.1),
        decoration: InputDecoration(
            // errorText: "something is wrong",
            contentPadding: EdgeInsets.all(10),
            filled: true,
            fillColor: ArgonColors.white,
            hintStyle: TextStyle(
              color: ArgonColors.muted,
            ),
            suffixIcon: suffixIcon,
            prefixIcon: prefixIcon,
            enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(12.0),
                borderSide: BorderSide(
                    color: borderColor, width: 1.0, style: BorderStyle.solid)),
            focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(12.0),
                borderSide: BorderSide(
                    color: borderColor, width: 1.0, style: BorderStyle.solid)),
            hintText: placeholder),
      ),
    );
  }
}

class EmailInputField extends StatelessWidget {
  final String placeholder;
  final Widget suffixIcon;
  final Widget prefixIcon;
  final Function onTap;
  final Function onChanged;
  final TextEditingController controller;
  final bool autofocus;
  final Color borderColor;
  final bool obscureText;
  final InputDecoration decoration;
  final bool isRequired;

  EmailInputField({
    this.placeholder,
    this.suffixIcon,
    this.prefixIcon,
    this.onTap,
    this.onChanged,
    this.autofocus = false,
    this.borderColor = ArgonColors.border,
    this.obscureText = false,
    this.decoration,
    this.controller,
    this.isRequired = false,
  });

  @override
  Widget build(BuildContext context) {
    return Input(
      placeholder: placeholder,
      suffixIcon: suffixIcon,
      prefixIcon: prefixIcon,
      onTap: onTap,
      onChanged: onChanged,
      autofocus: autofocus,
      borderColor: borderColor,
      obscureText: obscureText,
      decoration: decoration,
      controller: controller,
      validator: (v) {
        if (v.isValidEmail) {
          return null;
        } else {
          return 'Please enter a valid email';
        }
      },
    );
  }
}
2 Answers

the way I achieve this is by creating a 'Model'.

here is how you would achieve it in your case:

import 'package:flutter/material.dart';
import 'package:argon_flutter/constants/Theme.dart';
import 'package:argon_flutter/validations/validators.dart';

class ExampleModel {
  final String placeholder;
  final Widget suffixIcon;
  final Widget prefixIcon;
  final VoidCallback onTap;
  final Function(String) onChanged;
  final TextEditingController controller;
  final bool autofocus;
  final Color borderColor;
  final bool obscureText;
  final InputDecoration decoration;
  String Function(String) validator;

  ExampleModel({
    this.placeholder,
    this.suffixIcon,
    this.prefixIcon,
    this.onTap,
    this.onChanged,
    this.autofocus = false,
    this.borderColor = ArgonColors.border,
    this.obscureText = false,
    this.decoration,
    this.controller,
    this.validator,
  });
}

class Input extends StatelessWidget {
  final ExampleModel model;
  const Input(this.model);
  @override
  Widget build(BuildContext context) {
    return Container(
      child: TextFormField(
        cursorColor: ArgonColors.muted,
        cursorHeight: 14,
        onTap: model.onTap,
        onChanged: model.onChanged,
        controller: model.controller,
        autofocus: model.autofocus,
        obscureText: model.obscureText == true,
        validator: model.validator,
        // style: TextStyle(backgroundColor: ArgonColors.themeColor),
        // textAlignVertical: TextAlignVertical(y: 0.1),
        decoration: InputDecoration(
          // errorText: "something is wrong",
          contentPadding: EdgeInsets.all(10),
          filled: true,
          fillColor: ArgonColors.white,
          hintStyle: TextStyle(
            color: ArgonColors.muted,
          ),
          suffixIcon: model.suffixIcon,
          prefixIcon: model.prefixIcon,
          enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(12.0),
              borderSide: BorderSide(
                  color: model.borderColor,
                  width: 1.0,
                  style: BorderStyle.solid)),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12.0),
            borderSide: BorderSide(
              color: model.borderColor,
              width: 1.0,
              style: BorderStyle.solid,
            ),
          ),
          hintText: model.placeholder,
        ),
      ),
    );
  }
}

class EmailInputField extends StatelessWidget {
  final ExampleModel model;
  const EmailInputField(this.model);

  @override
  Widget build(BuildContext context) {
    model.validator = (v) {
      if (v.isValidEmail) {
        return null;
      } else {
        return 'Please enter a valid email';
      }
    };
    return Input(model);
  }
}

I think the concepts you're looking for are abstraction and interfaces. Learn more about it here.

Related