Saltar al contenido principal

Page

Este capítulo describe todo lo necesario para elaborar correctamente la clase Page, dentro del archivo base/feature_page.dart.

Nombrado

El nombre de la clase Page de un feature debe estar compuesto por el nombre de éste último seguido del sufijo Page, escrito en PascalCase.

/// Feature de iniciar sesión.
class LoginPage {}

/// Feature de perfil.
class ProfilePage {}

/// Feature del detalle de un contrato.
class ContractDetailPage {}
info

El nombrado de esta clase es generado automáticamente por el feature_brick_plus.

Extensión

La clase Page debe extender de StatelessWidget.

class LoginPage extends StatelessWidget {}

Constructor

El constructor de la clase Page debe ser constante.

class LoginPage extends StatelessWidget {
const LoginPage({super.key});
}

Parámetros del constructor

Cuando la página requiere parámetros de navegación, debe crearse una clase FeatureNameParams dentro del mismo archivo que los contenga:

class LoginParams {
const LoginParams({
required this.redirectPath,
this.isOnboarding = false,
});

final String redirectPath;
final bool isOnboarding;
}

class LoginPage extends StatelessWidget {
const LoginPage({required this.params, super.key});

final LoginParams params;
}

QueryParams

Para parámetros provenientes del query string de la ruta, se debe agregar un factory fromQueryParams a la clase Params:

class LoginParams {
const LoginParams({
required this.redirectPath,
this.isOnboarding = false,
});

final String redirectPath;
final bool isOnboarding;

factory LoginParams.fromQueryParams(Map<String, dynamic> queryParams) {
return LoginParams(
redirectPath: queryParams['redirect'] ?? '/',
isOnboarding: queryParams['onboarding'] == 'true',
);
}
}

Rutas

Todos los Pages deben tener sus variables de ruta declaradas, a excepción de los que sean un Tab dentro de un DefaultTabController o un Step dentro de un formulario multipágina.

Variable routeName

Variable estática y constante con el nombre de la ruta en minúsculas. Si tiene varias palabras, se debe usar kebab-case.

class LoginPage extends StatelessWidget {
const LoginPage({super.key});

static const routeName = 'login';
}

Si la ruta requiere un identificador:

class ContractDetailPage extends StatelessWidget {
const ContractDetailPage({super.key});

static const routeName = 'contract-detail/:id';
}

Variable path

Variable estática y constante con la barra / seguida del valor de routeName.

class LoginPage extends StatelessWidget {
const LoginPage({super.key});

static const routeName = 'login';
static const path = '/$routeName';
}
aviso

Todos los Pages con rutas deben tener obligatoriamente las variables routeName y path.

Método buildPath

Cuando la ruta requiere sustituir parámetros dinámicos, se debe crear un método estático buildPath:

class ContractDetailPage extends StatelessWidget {
const ContractDetailPage({super.key});

static const routeName = 'contract-detail/:id';
static const path = '/$routeName';

static String buildPath(String id) =>
'/$routeName'.replaceFirst(':id', id);
}

Declaración de BlocProviders

El método build de la clase Page siempre debe retornar un BlocProvider (o MultiBlocProvider), cuyo child siempre debe ser un Scaffold. La única excepción es el uso de PopScope.

peligro

El método build de Page no debe retornar ningún otro widget que no sean los indicados.

BlocProvider

class LoginPage extends StatelessWidget {
const LoginPage({super.key});

static const routeName = 'login';
static const path = '/$routeName';


Widget build(BuildContext context) {
return BlocProvider(
create: (context) => _LoginBloc(
loginUseCase: context.read<LoginUseCase>(),
),
child: Scaffold(
body: _LoginView(),
),
);
}
}

MultiBlocProvider

Cuando el feature requiere más de un bloc:


Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => _LoginBloc(
loginUseCase: context.read<LoginUseCase>(),
),
),
BlocProvider(
create: (context) => _OtherBloc(),
),
],
child: Scaffold(
body: _LoginView(),
),
);
}

Widget PopScope

Si se desea impedir que el usuario regrese a la vista anterior, se debe envolver el BlocProvider en un PopScope con canPop: false:


Widget build(BuildContext context) {
return PopScope(
canPop: false,
child: BlocProvider(
create: (context) => _LoginBloc(),
child: Scaffold(
body: _LoginView(),
),
),
);
}

Scaffolding

El Scaffold es el widget raíz del feature. Su atributo body debe ser siempre la clase _FeatureView. El resto de propiedades como appBar, floatingActionButton o bottomNavigationBar pueden definirse aquí según el diseño del feature.

child: Scaffold(
backgroundColor: ColorValues.bgPrimary(context),
body: _LoginView(),
),
info

Para más información sobre el widget Scaffold, consulta su documentación oficial.