Search code examples
flutterflutter-getx

Passing Constructor value from view to controller in getx


So this is my view that has constructor in it. I want to pass this constructor value products to my controller i.e WishListIconController. This view is actually a widget called in many views in my current project so I pass value to it using constructor.

 class WishListIconView extends GetView{
   final products;
   final category;

   WishListIconView({this.products, this.category});
   WishListServiceApi wishListService = locator<WishListServiceApi>();

   WishlistIconController wishListIconController =
   Get.put(WishlistIconController());

  @override
  Widget build(BuildContext context) {
  return Obx(
    () => locator<SharedPreferencesManager>().isKeyExists('isLogin') == true
        ? wishListIconController.isAdded.value == false
            ? IconButton(
                splashRadius: 3,
                constraints: BoxConstraints(),
                padding: EdgeInsets.all(0),
                icon: Icon(
                  Icons.favorite_border,
                  size: 18,
                  color: Colors.blue,
                ),
                onPressed: () async {
                  bool success = await wishListService.addToWishList(
                      products.id, category, products);
                },
              )
            : IconButton(
                splashRadius: 3,
                constraints: BoxConstraints(),
                padding: EdgeInsets.all(0),
                icon: Icon(
                  Icons.favorite,
                  size: 18,
                  color: Colors.blue,
                ),
                onPressed: () async {
                  bool success = await wishListService.deleteWishListItem(
                      products.id, category);
              
                },
              )
        : IconButton(
            splashRadius: 3,
            constraints: BoxConstraints(),
            padding: EdgeInsets.all(0),
            icon: Icon(
              Icons.favorite_border,
              size: 18,
              color: Colors.blue,
            ),
            onPressed: () {
              Fluttertoast.showToast(
                  msg: "Please login to add product to wishlist",
                  toastLength: Toast.LENGTH_SHORT,
                  gravity: ToastGravity.TOP,
                  backgroundColor: Colors.blue[300],
                  textColor: Colors.white,
                  fontSize: 16.0);
            },
          ));
   }
 }

This is my controller. I want to pass product here to so I can create functions using products value.

 class WishlistIconController extends GetxController {
     WishListServiceApi wishListServiceApi = locator<WishListServiceApi>();
     var isAdded = false.obs;

   @override
  void onInit() {
    super.onInit();
    isInWishList();
  }

 isInWishList() {
   isAdded.value = wishListServiceApi.wishListResponse
    .any((element) => element.id == products.id);

  update();
 }

 @override
  void onReady() {
  super.onReady();
  isInWishList();
   }
 }

Solution

  • Here is the complete example, of nested controllers,

    In first controller make Future Constructor and call your required function in it

    class FirstController extends GetxController {
     
      bool? flag;
    
      //make a future constructor 
      Future<FirstController> init() async {
        await getFlagValue();
    
        //This is important
        return this;
      }
    
      @override
      void onInit() {
        super.onInit();
        otherFunction();
      }
    
      getFlagValue() async {
        //call your api here and set the value
        await Future.delayed(Duration(seconds: 1));
        flag = true;
        update();
      }
    
      otherFunction() async {
        print('Second Function');
      }
    }
    

    Now simply get this flag into second controller by find function.

    class SecondController extends GetxController {
    
      //get flag value
      bool? _flagValue = Get.find<FirstController>().flag;
    
      @override
      void onInit() async {
        super.onInit();
        printStatus();
      }
    
      printStatus() {
        if(_flagValue){
           print("Flag is true");
         }else{
           print("Flag is false");
         } 
      }
    
    }
    

    And last but not the least the CommonBinder would change like:

    class CommonBinder extends Bindings {
    
      //Make it async
      @override
      void dependencies() async {
    
        Get.put(ZeroController());
        //Use putAsync and call your future constructor in it
        await Get.putAsync<FirstController>(
            () async => await FirstController().init());
        Get.put(SecondController());
      }
    }
    

    And your main function:

    return GetMaterialApp(
          title: 'Example Project',
          debugShowCheckedModeBanner: false,
          defaultTransition: Transition.size,
          initialBinding: CommonBinder(),
          home: SplashScreen(),
        );
    

    Hope, you understand the solution