Instance of 'Response<dynamic>' flutter Api Consumption - flutter

I am trying to make a post request in flutter using chopper. I have made an ApiService.dart file as
a generator file.
import 'package:bindle/Chopper/Models/LoginResponse.dart';
import 'package:chopper/chopper.dart';
part 'ApiService.chopper.dart';
#ChopperApi(baseUrl: 'http://192.168.1.20/bindal/api/v1/user/')
abstract class ApiService extends ChopperService {
#Post(path: "login")
Future<Response<LoginResponse>> doLogin([
#Header('auth_key') String authType,
#Query('email') String email,
#Query('password') String password,
#Query('userType') String userType,
]);
static ApiService create() {
final client = ChopperClient(
// The first part of the URL is now here
baseUrl: 'http://192.168.1.20/bindal/api/v1/user/',
services: [
// The generated implementation
_$ApiService(),
],
interceptors: [
HttpLoggingInterceptor()
],
// Converts data to & from JSON and adds the application/json header.
converter: JsonConverter(),
);
// The generated class with the ChopperClient passed in
return _$ApiService(client);
}
}
And this is my generated file.
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'ApiService.dart';
// **************************************************************************
// ChopperGenerator
// **************************************************************************
class _$ApiService extends ApiService {
_$ApiService([ChopperClient client]) {
if (client == null) return;
this.client = client;
}
final definitionType = ApiService;
Future<Response<LoginResponse>> doLogin(
[String authType, String email, String password, String userType]) {
final $url = 'http://192.168.1.20/bindal/api/v1/user/login';
final Map<String, dynamic> $params = {
'email': email,
'password': password,
'userType': userType
};
final $headers = {'auth_key': authType};
final $request = Request('POST', $url, client.baseUrl,
parameters: $params, headers: $headers);
return client.send<LoginResponse, LoginResponse>($request);
}
}
Next what i Did is i generated a model class called as LoginResponse where I have to fetch the data.
abstract class LoginResponse implements Built<LoginResponse, LoginResponseBuilder> {
int get status;
String get message;
LoginResponse._();
factory LoginResponse([void Function(LoginResponseBuilder) updates]) = _$LoginResponse;
static LoginResponse fromJson(String jsonString){
return serializers.deserializeWith(LoginResponse.serializer, json.decode(jsonString));
}
static Serializer<LoginResponse> get serializer => _$loginResponseSerializer;
}
this is the generated file for the above LoginResponse.dart file using built_value generator
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'LoginResponse.dart';
// **************************************************************************
// BuiltValueGenerator
// **************************************************************************
Serializer<LoginResponse> _$loginResponseSerializer =
new _$LoginResponseSerializer();
class _$LoginResponseSerializer implements StructuredSerializer<LoginResponse> {
#override
final Iterable<Type> types = const [LoginResponse, _$LoginResponse];
#override
final String wireName = 'LoginResponse';
#override
Iterable<Object> serialize(Serializers serializers, LoginResponse object,
{FullType specifiedType = FullType.unspecified}) {
final result = <Object>[
'status',
serializers.serialize(object.status, specifiedType: const FullType(int)),
'message',
serializers.serialize(object.message,
specifiedType: const FullType(String)),
];
return result;
}
#override
LoginResponse deserialize(
Serializers serializers, Iterable<Object> serialized,
{FullType specifiedType = FullType.unspecified}) {
final result = new LoginResponseBuilder();
final iterator = serialized.iterator;
while (iterator.moveNext()) {
final key = iterator.current as String;
iterator.moveNext();
final dynamic value = iterator.current;
switch (key) {
case 'status':
result.status = serializers.deserialize(value,
specifiedType: const FullType(int)) as int;
break;
case 'message':
result.message = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
}
}
return result.build();
}
}
class _$LoginResponse extends LoginResponse {
#override
final int status;
#override
final String message;
factory _$LoginResponse([void Function(LoginResponseBuilder) updates]) =>
(new LoginResponseBuilder()..update(updates)).build();
_$LoginResponse._({this.status, this.message}) : super._() {
if (status == null) {
throw new BuiltValueNullFieldError('LoginResponse', 'status');
}
if (message == null) {
throw new BuiltValueNullFieldError('LoginResponse', 'message');
}
}
#override
LoginResponse rebuild(void Function(LoginResponseBuilder) updates) =>
(toBuilder()..update(updates)).build();
#override
LoginResponseBuilder toBuilder() => new LoginResponseBuilder()..replace(this);
#override
bool operator ==(Object other) {
if (identical(other, this)) return true;
return other is LoginResponse &&
status == other.status &&
message == other.message;
}
#override
int get hashCode {
return $jf($jc($jc(0, status.hashCode), message.hashCode));
}
#override
String toString() {
return (newBuiltValueToStringHelper('LoginResponse')
..add('status', status)
..add('message', message))
.toString();
}
}
class LoginResponseBuilder
implements Builder<LoginResponse, LoginResponseBuilder> {
_$LoginResponse _$v;
int _status;
int get status => _$this._status;
set status(int status) => _$this._status = status;
String _message;
String get message => _$this._message;
set message(String message) => _$this._message = message;
LoginResponseBuilder();
LoginResponseBuilder get _$this {
if (_$v != null) {
_status = _$v.status;
_message = _$v.message;
_$v = null;
}
return this;
}
#override
void replace(LoginResponse other) {
if (other == null) {
throw new ArgumentError.notNull('other');
}
_$v = other as _$LoginResponse;
}
#override
void update(void Function(LoginResponseBuilder) updates) {
if (updates != null) updates(this);
}
#override
_$LoginResponse build() {
final _$result =
_$v ?? new _$LoginResponse._(status: status, message: message);
replace(_$result);
return _$result;
}
}
finally i called my api in the login page as
void doLogin(String email, String pass, BuildContext context) async {
try {
final response = await Provider.of<ApiService>(context)
.doLogin("d1d2fe0514f7d5c748c0e7e085b36f74","arpit1692#gmail.com",
"e10adc3949ba59abbe56e057f20f883e","App");
print(response.body);
} catch (e) {
print(e);
}
}
Which ultimately gives me Exception as => Instance of 'Response dynamic'
Please help me for what I am doing wrong.

The reason why the Response returns dyanmic is because the response wasn't serialized to the model you've defined. If LoginResponse is the model that should be used for the response, the LoginResponse class should have fromJson() that should serialize the json response. You can follow this guide to help you manage json serialization.

Related

how to make return of model class into list

i have model called LoginPageModel, but the problem is my api have more than one CODD_VALU and CODD_DESC. and i dont know how to return it as list or an array.
This is my LoginPageModel
class LoginPageModel {
String CODD_VALU;
String CODD_DESC;
LoginPageModel({required this.CODD_VALU, required this.CODD_DESC});
static Future<LoginPageModel> connect(String CODD_VALU) async {
Uri url = Uri.parse("http://deltaprima.rmdoo.com/api/niv/all");
var response = await http.get(
url,
headers: {
"CompanyCode": CODD_VALU,
},
);
var dataJson = jsonDecode(response.body);
return LoginPageModel(
CODD_VALU: dataJson[0]["CODD_VALU"],
CODD_DESC: dataJson[0]["CODD_DESC"],
);
}
}
and this is response of my api (Im using postma)
[
{
"CODD_DESC": "DELTA PRIMA",
"CODD_VALU": "01"
},
{
"CODD_DESC": "SAMPLE",
"CODD_VALU": "02"
}
]
and also this is how i will call return value of LoginPageModel Like this
LoginPageModel.connect(data["CODD_VALU"]).then((value) {
print(value.CODD_DESC);
setState(() {
dataOffice = value.CODD_DESC;
});
}
import 'package:wnetworking/wnetworking.dart';
class Offices {
final String name, value;
/* ---------------------------------------------------------------------------- */
Offices(this.name, this.value);
/* ---------------------------------------------------------------------------- */
#override
String toString() => '$name [$value]';
}
class DeltaPrima {
DeltaPrima._();
/* ---------------------------------------------------------------------------- */
static const _url = 'http://deltaprima.rmdoo.com/api/office/all';
/* ---------------------------------------------------------------------------- */
static Future<List<Offices>?> getOffices(String token) async {
var result = (await HttpReqService.get<List>(_url, headers: {'CompanyCode':token}));
if (result == null) return null;
var list = result
.cast<JMap>()
.map((m) => Offices(m['CODD_DESC']!, m['CODD_VALU']!))
.toList()
;
print('Objects => $list');
return list;
}
}
void main(List<String> args) async {
await DeltaPrima.getOffices('MW');
print('Job done!');
}
Output:
Objects => [DELTA PRIMA [01], SAMPLE [02]]
Job done!
The easiest way is as follows:
You need to use a tool that passes Json to Dart class.
For example from https://app.quicktype.io and the result is:
// To parse this JSON data, do
//
// final loginPageModel = loginPageModelFromJson(jsonString);
import 'dart:convert';
List<LoginPageModel> loginPageModelFromJson(String str) =>
List<LoginPageModel>.from(
json.decode(str).map((x) => LoginPageModel.fromJson(x)));
String loginPageModelToJson(List<LoginPageModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class LoginPageModel {
LoginPageModel({
required this.coddDesc,
required this.coddValu,
});
String coddDesc;
String coddValu;
factory LoginPageModel.fromJson(Map<String, dynamic> json) => LoginPageModel(
coddDesc: json["CODD_DESC"],
coddValu: json["CODD_VALU"],
);
Map<String, dynamic> toJson() => {
"CODD_DESC": coddDesc,
"CODD_VALU": coddValu,
};
}
Update Your Login Page Model Like this.
class LoginPageModel {
String CODD_VALU;
String CODD_DESC;
LoginPageModel({required this.CODD_VALU, required this.CODD_DESC});
factory LoginPageModel.fromJson(Map<String, dynamic> json) => LoginPageModel(
coddDesc: json["CODD_DESC"],
coddValu: json["CODD_VALU"],
);
static Future<List<LoginPageModel>> connect(String CODD_VALU) async {
Uri url = Uri.parse("http://deltaprima.rmdoo.com/api/niv/all");
var response = await http.get(
url,
headers: {
"CompanyCode": CODD_VALU,
},
);
var dataJson = jsonDecode(response.body);
Iterable l = json.decode(response.body);
List<LoginPageModel> listmodel = List<LoginPageModel>.from(l.map((model)=> LoginPageModel.fromJson(model)));
return listmodel;
}
}

A value of type 'List<dynamic>' can't be assigned to a variable of type 'List<Todo>'. Try changing the type of the variable

im new in flutter , and i want to display my data from api json to my app with ResteApi ,
i made a model like that :
class Todo {
final int id;
final String title;
final bool completed;
Todo({required this.id, required this.title, required this.completed});
factory Todo.fromJson(Map<String, dynamic> json) {
return Todo(
id: json["id"] as int,
title: json["title"] as String,
completed: json["completed"] as bool);
}
Map<String, dynamic> toJson() => {'title': title, 'completed': completed};
#override
String toString() {
return 'Todo{id: $id, title: $title, completed: $completed}';
}
}
And a methode get in service class Like that :
final String apiUrl = "https://jsonplaceholder.typicode.com/todos";
Future<List<Todo>> getCases() async {
Response res = await get(Uri.parse(apiUrl));
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Todo> todo = body.map((dynamic item) => todo.fromJson(item)).toList();
return todo;
} else {
throw "Failed to load cases list";
}
}
but this errors it display to me:
A value of type 'List<dynamic>' can't be assigned to a variable of type 'List<Todo>'.
Try changing the type of the variable, or casting the right-hand type to 'List<Todo>'
how can i fix it
There is a typo todo.fromJson, it will be Todo.fromJson
List<Todo> todo = body.map((dynamic item) => Todo.fromJson(item)).toList();
Also it is better to accept null data
List<dynamic>? body = jsonDecode(res.body);
final todo =
body?.map((dynamic item) => Todo.fromJson(item)).toList() ?? [];
return todo;
Try this:
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Todo> todo = body.map<Todo>((item) => Todo.fromJson(item)).toList();
return todo;
} else {
throw "Failed to load cases list";
}
// create function like this inside ApiFunctionsCall() class
Future<String?> dataListApiCalls() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
final response = await http.get(Uri.parse('url_of_api'));
if (response.statusCode == 200) {
//print(response.body);
return response.body;
}
} else {
print("check internet connection");
}
} catch (e) {
print(e);
}
}
//then in call function other file
// create list
List<Todo> searchDataList = [];
// other function
void getDataList() async {
final response = await ApiFunctionsCall().dataListApiCalls();
final searchModalDataClass = jsonDecode(response!);
setState(() {
for (var i = 0; i < searchModalDataClass.data.length; i++) {
Todo todo = Todo(
id: searchModalDataClass.data[i].id,
email: searchModalDataClass.data[i].email,
searchDataList.add(todo);
}
});
}

how to pass the model class and return data in flutter

Model class:
#JsonSerializable()
class EmpVerifyEntity extends Equatable {
#JsonKey(name: "access_token")
final String accessToken;
final EmpVerifyEmployee employee;
const EmpVerifyEntity(this.accessToken, this.employee);
factory EmpVerifyEntity.fromJson(Map<String, dynamic> json) =>
_$EmpVerifyEntityFromJson(json);
Map<String, dynamic> toJson() => _$EmpVerifyEntityToJson(this);
static const empty = EmpVerifyEntity(
'123',
EmpVerifyEmployee(
'1', 'avatar', 'sId', 'empName', 'empId', 'designation', 1));
#override
String toString() {
return jsonEncode(this);
}
#override
// TODO: implement props
List<Object?> get props => [accessToken, employee];
}
#JsonSerializable()
class EmpVerifyEmployee extends Equatable {
#JsonKey(name: "password")
final String password;
final String avatar;
#JsonKey(name: "_id")
final String sId;
#JsonKey(name: "emp_name")
final String empName;
#JsonKey(name: "emp_id")
final String empId;
final String designation;
#JsonKey(name: "__v")
final int iV;
const EmpVerifyEmployee(this.password, this.avatar, this.sId, this.empName,
this.empId, this.designation, this.iV);
factory EmpVerifyEmployee.fromJson(Map<String, dynamic> json) =>
_$EmpVerifyEmployeeFromJson(json);
Map<String, dynamic> toJson() => _$EmpVerifyEmployeeToJson(this);
static const empty = const EmpVerifyEmployee(
'password', 'avatar', 'sId', 'empName', 'empId', 'designation', 1);
#override
String toString() {
return jsonEncode(this);
}
#override
// TODO: implement props
List<Object?> get props =>
[password, avatar, sId, empName, empId, designation, iV];
}
auth repo:
class AuthenticationRepository {
Future<void> logIn({ //login process
required String username,
required String password,
}) async {
print("------------------");
print(username);
var res = await http.post(
Uri.parse("https://cots.com/api/v1/employee/login"),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json'
},
body: jsonEncode({"emp_id": username, "password": password}));
dynamic data = json.decode(res.body);
print(data);
if (data['employee']["is_active"] == true) {
_controller.add(AuthenticationStatus.authenticated);///here it shows authenticated
}
}
User Repo:
class UserRepository {
EmpVerifyEntity? _empVerifyEntity;
UserRepository(this._empVerifyEntity);
Future<EmpVerifyEntity?> getUser() async {
if (_empVerifyEntity != null) {
return _empVerifyEntity;
}
}
}
Auth Bloc:
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
AuthenticationBloc({
required AuthenticationRepository authenticationRepository,
required UserRepository userRepository,
}) : _authenticationRepository = authenticationRepository,
_userRepository = userRepository,
super(const AuthenticationState.unknown()) {
on<AuthenticationStatusChanged>(_onAuthenticationStatusChanged);
on<AuthenticationLogoutRequested>(_onAuthenticationLogoutRequested);
_authenticationStatusSubscription = _authenticationRepository.status.listen(
(status) => add(AuthenticationStatusChanged(status)),
);
}
final AuthenticationRepository _authenticationRepository;
final UserRepository _userRepository;
late StreamSubscription<AuthenticationStatus>
_authenticationStatusSubscription;
#override
Future<void> close() {
_authenticationStatusSubscription.cancel();
_authenticationRepository.dispose();
return super.close();
}
void _onAuthenticationStatusChanged(
AuthenticationStatusChanged event,
Emitter<AuthenticationState> emit,
) async {
switch (event.status) {
case AuthenticationStatus.unauthenticated:
return emit(const AuthenticationState.unauthenticated());
case AuthenticationStatus.authenticated:
final user = await _tryGetUser();
return emit(user != null
? AuthenticationState.authenticated(user)
: AuthenticationState.unauthenticated());
default:
return emit(const AuthenticationState.unknown());
}
}
void _onAuthenticationLogoutRequested(
AuthenticationLogoutRequested event,
Emitter<AuthenticationState> emit,
) {
_authenticationRepository.logOut();
}
Future<EmpVerifyEntity?> _tryGetUser() async {
try {
final user = await _userRepository.getUser();
return user; /////----------------Here I'm getting null as a user
} catch (e) {
print(e);
}
}
}
I can able to do login but can't able to fetch data because it shows null, In login method I should return data so that I can able to fetch. It is authenticated but user data is null, how to pass the return data to userRepo so that I can fetch in authBloc.
-------------------------------------THank you--------------------------

Can't emit state conditionally on stream values (Flutter-Bloc)

In constructor of the following bloc, I subscribe to a stream of firebase auth changes. go_router handles redirection.
When a user signs in/out _onAppUserChanged is called. If successfully signed in, I await for user's firestore data to be fetched. If there is, among the data, a location entry, I need to emit AppState with status==AppStatus.hasLocation if and only if my CatalogBlog has emitted state with status==CatalogStatus.loaded. Neither await for (var catalogState in _catalogBloc.stream) nor adding a listener will work. AppState with status: AppStatus.hasLocation won't be emmited although CatalogBloc will definatelly emit with status==CatalogStatus.loaded at some point.
class AppBloc extends Bloc<AppEvent, AppState> {
final UserRepository _userRepository;
final AuthRepository _authRepository;
final CatalogBloc _catalogBloc;
AppBloc(
UserRepository userRepository,
AuthRepository authRepository,
PrefsRepository prefsRepository,
CatalogBloc catalogBloc,
) : _userRepository = userRepository,
_authRepository = authRepository,
_catalogBloc = catalogBloc,
super(const AppState()) {
on<AppUserChanged>(_onAppUserChanged);
on<AppSignOutRequested>(_onAppSignOutRequested);
on<AppSelectedLocationSet>(_onAppSelectedLocationSet);
_authRepository.getAuthStateChanges().listen((String uid) {
add(AppUserChanged(uid));
});
}
void _onAppUserChanged(AppUserChanged event, Emitter<AppState> emit) async {
if (event.uid.isEmpty) {
emit(const AppState(status: AppStatus.noUser));
} else {
await for (var user in _userRepository.getUserData(event.uid)) {
if (_catalogBloc.state.status == CatalogStatus.initial) {
_catalogBloc.add(CatalogStarted());
}
if (user.locations.isEmpty) {
// Go to '/location_search'
emit(AppState(status: AppStatus.noLocation, user: user));
} else {
// Wait for catalog data to be fetched, then go to '/catalog'
await for (var catalogState in _catalogBloc.stream) {
if (catalogState.status == CatalogStatus.loaded) {
emit(AppState(
status: AppStatus.hasLocation,
user: user,
selectedLocation: user.prefLocation,
));
}
}
}
}
}
}
}
App State:
enum AppStatus { initial, hasLocation, noLocation, noUser, error }
class AppState extends Equatable {
final AppStatus status;
final User user;
final Location? selectedLocation;
const AppState({
this.status = AppStatus.initial,
this.user = const User(),
this.selectedLocation = const Location(),
});
#override
List<Object?> get props => [status, user, selectedLocation];
AppState copyWith({
AppStatus? status,
User? user,
Location? selectedLocation,
}) {
return AppState(
status: status ?? this.status,
user: user ?? this.user,
selectedLocation: selectedLocation ?? this.selectedLocation);
}
}
AppEvents:
abstract class AppEvent extends Equatable {
const AppEvent();
#override
List<Object> get props => [];
}
class AppUserChanged extends AppEvent {
final String uid;
const AppUserChanged(this.uid);
#override
List<Object> get props => [uid];
}
User repo:
class UserRepository {
final FirebaseFirestore _db = FirebaseFirestore.instance;
late User? user;
Stream<User> getUserData(String uid) {
var documentStream = _db.collection('users').doc(uid).snapshots();
return documentStream.map((snapshot) {
var data = snapshot.data();
if (data != null) {
user = User.fromJson(data);
return user!;
}
throw Exception("Firestore entry was not created for the signed in user");
});
}
...
}

Flutter Riverpod context.read(providerref) doesn't give same reference of stateNotifier when call in two different functions of a Widget

I am setting values of variables declared in View Model class which is a StateNotifier, inside a function of widget. When I try to access the values of those variables from a different function of same widget, their values are null. I have debugged code to verify that first function is setting values correctly.
Any help will be highly appreciated.
Here is cutdown version of my StateNotifier
class ProductViewModel extends StateNotifier<ProductState> {
String errorMessage;
Product product;
final ProductService productService;
final CategoryService categoryService;
final BrandService brandService;
final TranslatorService translatorService;
final ProductOptionsViewModel productOptionsViewModel;
final ProductVariantViewModel productVariantViewModel;
ProductViewModel(this.productService, this.categoryService, this.brandService, this.translatorService,
this.productOptionsViewModel, this.productVariantViewModel)
: super(ProductInitial());
String productId;
List<SizeEnum> _sizes;
String _selectedBrand;
String _selectedCategory;
String _selectedStore;
String _productName;
String _productIntlName;
String _sku;
String get selectedBrand => _selectedBrand;
set selectedBrand(String value) {
_selectedBrand = value;
}
String get selectedCategory => _selectedCategory;
set selectedCategory(String value) {
_selectedCategory = value;
}
String get selectedStore => _selectedStore;
set selectedStore(String value) {
_selectedStore = value;
}
String get productName => _productName;
set productName(String value) {
_productName = value;
}
String get productIntlName => _productIntlName;
set productIntlName(String value) {
_productIntlName = value;
}
String get sku => _sku;
set sku(String value) {
_sku = value;
}
Future<bool> saveProductDetails() async {
bool isSave = false;
bool imageSaved = await saveProductImage();
if (!imageSaved) return imageSaved;
List<String> searchKeywords = indexProductName(_productName);
List<String> searchTag1 = _searchTag1 != null ? indexProductName(_searchTag1) : null;
List<String> searchTag2 = _searchTag2 != null ? indexProductName(_searchTag2) : null;
List<String> searchTag3 = _searchTag3 != null ? indexProductName(_searchTag3) : null;
if (deal != null && _dealsAddedDateTime == null) {
_dealsAddedDateTime = DateTime.now();
}
print(productOptionsViewModel.toString());
Product _product = Product(
productId: productId,
name: _productName,
intlName: _productIntlName,
category: FirebaseFirestore.instance.doc(_selectedCategory),
brand: FirebaseFirestore.instance.doc(_selectedBrand),
sku: _sku,
quantity: _quantity,
price: _price,
containSizes: productOptionsViewModel.sizes,
containColors: productOptionsViewModel.colors,
accessory: productOptionsViewModel.accessory ,
salesTaxApplicable: productOptionsViewModel.salesTax,
);
isSave = await productService.saveProduct(_product);
if (!isSave) {
errorMessage = "Error in saving product information";
} else {
productId = productService.newProductId;
}
return isSave;
}
}
StateNotifierProvider declaration
final productViewModelProvider = StateNotifierProvider.autoDispose<ProductViewModel,ProductState>((ref) => ProductViewModel(
ref.watch(productServiceProvider),
ref.watch(categoryServiceProvider),
ref.watch(brandServiceProvider),
ref.watch(translatorServiceProvider),
ref.watch(productOptionsViewModelProvider),
ref.watch(productVariantViewModelProvider)));
UI Functions
I set values in validateProduct and read values again in saveProductDetails.
Future<bool> validateProduct() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
final model = context.read(productViewModelProvider.notifier);
final storeViewModel = context.read(storeViewModelProvider.notifier);
var _store = await storeViewModel.getMyStore();
model.productName = _productName;
model.productIntlName = _productIntlName;
model.sku = _sku;
model.quantity = _quantity;
model.price = _price;
model.selectedBrand = _selectedBrand;
model.selectedCategory = _selectedCategory;
model.selectedStore = _storeCode;
model.description = _productDescription;
model.manufacturerLink = _manufacturerLink;
model.searchTag1 = _searchTag1;
model.searchTag2 = _searchTag2;
model.searchTag3 = _searchTag3;
if (model.addedDateTime == null) {
model.addedDateTime = DateTime.now();
}
if (_storeCode == null) {
_storeCode = _store.store;
}
if (model.selectedStore == null) {
model.selectedStore = _storeCode;
}
return true;
}
else return false;
}
Future<bool> saveProductDetails() async {
final model = context.read(productViewModelProvider.notifier);
bool isProductSaved = await model.saveProductDetails();
if (isProductSaved) {
if (_isProductExist) {
displayMessage(context, "Product Information Updated");
} else
displayMessage(context, "Product Information Saved");
_formSaved = true;
isFormChanged = false;
return true;
} else if (isProductSaved == false) {
_formSaved = false;
displayMessage(context, model.errorMessage);
}
return isProductSaved;
}
State
abstract class ProductState {
const ProductState();
}
class ProductInitial extends ProductState {
const ProductInitial();
}
class ProductLoading extends ProductState {
const ProductLoading();
}
class ProductLoaded extends ProductState {
final Product product;
ProductLoaded(this.product);
#override
bool operator ==(Object other) =>
identical(this, other) || other is ProductLoaded && runtimeType == other.runtimeType && product == other.product;
#override
int get hashCode => product.hashCode;
}
class ProductSaving extends ProductState {
const ProductSaving();
}
class ProductSaved extends ProductState {
final Product product;
ProductSaved(this.product);
#override
bool operator ==(Object other) =>
identical(this, other) || other is ProductSaved && runtimeType == other.runtimeType && product == other.product;
#override
int get hashCode => product.hashCode;
}
class ProductError extends ProductState {
final String errorMessage;
ProductError(this.errorMessage);
}
Remove .autoDispose modifier
final productViewModelProvider = StateNotifierProvider<ProductViewModel,ProductState>((ref) => ProductViewModel(
ref.watch(productServiceProvider),
ref.watch(categoryServiceProvider),
ref.watch(brandServiceProvider),
ref.watch(translatorServiceProvider),
ref.watch(productOptionsViewModelProvider),
ref.watch(productVariantViewModelProvider)));