I have a TemplateView page that has a content parameter that hosts content that changes depending on my application. Each content has a specific provider. On the other hand, my TemplateView page has a button which calls a validation function common to each provider.
Here the example of my app (in green my TemplateView, in red the content who change):
Here is a simplified code of Template View. We see the call to the content and the validation button which calls the provider of the content ContentView1.
class TemplateView extends StatelessWidget{
final String title;
final StatelessWidget content;
TemplateView ({
Key? key,
required this.title,
required this.content,
required this.validationMessage,
}) : super(key: key);
@override
Widget build(BuildContext context)
{
return GestureDetector(
onTap: (() => FocusScope.of(context).requestFocus(FocusNode())),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(title),
),
body : _buildBody(context),
),
),
);
}
Widget _buildBody(BuildContext context)
{
// Here the call of my provider for the ContentView1
var _messageProvider = Provider.of<ContentView1Provider>(context);
return Column(
children: [
SingleChildScrollView(
child: Container(
child: content,
),
),
InkWell(
child: Container(
child: Text('SAVE'),
),
onTap: () => _messageProvider.validation()
),
],
);
}
}
And here, how I call the TemplateView in my router:
case RouterName.kContentView1:
return CupertinoPageRoute(
builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
create: (BuildContext context) => ContentView1Provider(),
child: TemplateView(
title: "Content 1 page",
message: ContentView1(),
),
)
);
All are working, now like I said the contents will change but my TemplateView is common. I therefore cannot enter in the TemplateView the call to the provider directly since it will change depending on the pages.
So I want to make the call to the provider in the TemplateView settings but it doesn't work.
My new TemplateView:
class TemplateView extends StatelessWidget{
final String title;
final StatelessWidget content;
final Function validationMessage; // => I added this line
TemplateView({
Key? key,
required this.title,
required this.content,
required this.validationMessage, // => I added this line
}) : super(key: key);
@override
Widget build(BuildContext context)
{
// => I remove the call of the provider line
return GestureDetector(
onTap: (() => FocusScope.of(context).requestFocus(FocusNode())),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(title),
),
body : _buildBody(context),
),
),
);
}
Widget _buildBody(BuildContext context)
{
return Column(
children: [
SingleChildScrollView(
child: Container(
child: content,
),
),
InkWell(
child: Container(
child: Text('SAVE'),
),
onTap: () => validationMessage() // => I changed this line
),
],
);
}
}
My new router :
case RouterName.kContentView1:
return CupertinoPageRoute(
builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
create: (BuildContext context) => ContentView1Provider(),
child: TemplateView(
title: "Content 1 page",
message: Content1View(),
validationMessage: () => Provider.of<ContentView1Provider>(context).validation(),
),
)
);
It doesn't work, how to do this ?
EDIT with the solution I added Consumer in my router :
case RouterName.kContentView1:
return CupertinoPageRoute(
builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
create: (BuildContext context) => ContentView1Provider(),
child: TemplateView(
title: "Content 1 page",
message: Consumer<ContentView1Provider>(builder :(ctx , provider , child){
return ContentView1();
}),
validationMessage: () => Provider.of<ContentView1Provider>(context).validation(),
),
)
);
CodePudding user response:
I am not sure if I understand this case well, but I just tell an Idea if it is work and if I understood what you ask : in your route pass provider to the Tamplate page :
case RouterName.kContentView1:
return CupertinoPageRoute(
builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
create: (BuildContext context) => ContentView1Provider(),
child: TemplateView(
provider : ContentView1Provider , // add this line
title: "Content 1 page",
message: Content1View(),
validationMessage: () => Provider.of<ContentView1Provider>(context).saveMessage(),
),
)
);
in template view recieve this provider :
class TemplateView extends StatelessWidget{
final provider; // add this line
final String title;
final StatelessWidget content;
final Function validationMessage; // => I added this line
TemplateView({
Key? key,
required this.provider, // add this line
required this.title,
required this.content,
required this.validationMessage, // => I added this line
}) : super(key: key);
now You can use Consumer with provider you recieved for each content :
return Consumer<provider>(builder :(ctx , provider , child){
return //what you want ....;
})
May I have missunderstood