mightycode Newton
mightycode Newton

Reputation: 3949

How do I refactor if else statements of API calls?

I have a search button and depending upon the selected option from a user, the corresponding API call will be triggered. But I have now a bunch of if else statements.

So my question is, can I refactor this? But without a switch case?

 searchFor() {
    if (this.selectedSearch === 'Registratie') {
      this.extendedSearchService
        .filerByRegistration(this.selectedValue, this.startDate)
        .subscribe(filterByRegistration => {
          this.filterparticipant.emit(filterByRegistration);
        });
    }

    if (this.selectedSearch === 'Chat') {
      this.extendedSearchService.filterByChat(this.startDate).subscribe(filterByChat => {
        this.filterparticipant.emit(filterByChat);
      });
    }

    if (this.selectedSearch === 'Inlog') {
      console.log('INlog');
      this.extendedSearchService.filterByInlog(this.startDate).subscribe(filterByInlog => {
        this.filterparticipant.emit(filterByInlog);
      });
    }

    if (this.selectedSearch === 'QrCode') {
      this.extendedSearchService
        .filterByQrCodes(this.selectedValue, this.startDate, this.selectedQrcode)
        .subscribe(fitlerByQrCode => {
          this.filterparticipant.emit(fitlerByQrCode);
        });
    }

    if (this.selectedSearch === 'Doelen') {
      this.extendedSearchService
        .filerByChallenge(this.selectedValue, this.startDate, this.selectedValueOptie, this.selectedValueProgressie)
        .subscribe(filterByChallenge => {
          this.filterparticipant.emit(filterByChallenge);
        });
    }

    if (this.selectedSearch === 'Vcheq') {
      this.extendedSearchService
        .filterByVchecCode(this.selectedValue, this.startDate, this.selectedVcheqOption)
        .subscribe(filterByVcheqCode => {
          this.filterparticipant.emit(filterByVcheqCode);
        });
    }
  }

Thank you

I have it now like this:

 searchFor() {
    const filter = (method, params) => {
      this.extendedSearchService[method](...params).subscribe(filter => {
        this.filterparticipant.emit(filter);
      });

      const filters = {
        Registratie: filter('Registratie', [this.selectedValue, this.startDate]),
        Chat: filter('Chat', [this.startDate]),
        Inlog: filter('Inlog', this.startDate),
        QrCode: filter('QrCode', [this.selectedValue, this.startDate, this.selectedQrcode]),
        Doelen: filter('Doelen', [
          this.selectedValue,
          this.startDate,
          this.selectedValueOptie,
          this.selectedValueProgressie
        ]),
        Vcheq: filter('Vcheq', [this.selectedValue, this.startDate, this.selectedVcheqOption])
      };

      if (filters[this.selectedSearch]) {
        filters[this.selectedSearch]();
      }
    };
}

And it compiles, but the filter doesnt work.

if I do this:

 searchFor() {
    const filter = (method, params) => {
      this.extendedSearchService[method](...params).subscribe(filter => {
        console.log('Filter');
        this.filterparticipant.emit(filter);
      });
    };

I get this error:

ExtendedSearchComponent.html:90 ERROR TypeError: Cannot read property 'apply' of undefined
    at filter (extended-search.component.ts:211)
    at 

On this line:

 this.extendedSearchService[method](...params).subscribe(filter => {
        console.log('Filter');

I have it so:

searchFor() {

      const filter = (method, params) => {
        this.extendedSearchService[method](...params).subscribe(filter => {
          console.log(method);
          this.filterparticipant.emit(filter);
        });
      };

      const filters = {
        Registratie: filter('filterByRegistration', [this.selectedValue, this.startDate]),
        Chat: filter('filterByChat', [this.startDate]),
        Inlog: filter('filterByInlog', [this.startDate]),
        QrCode: filter('filterByQrCodes', [this.selectedValue, this.startDate, this.selectedQrcode]),
        Doelen: filter('filerByChallenge', [this.selectedValue, this.startDate, this.selectedValueOptie, this.selectedValueProgressie]),
        Vcheq: filter('filterByVchecCode', [this.selectedValue, this.startDate, this.selectedVcheqOption]),
     }

      if (filters[this.selectedSearch]) {
        filters[this.selectedSearch]();
      }
    }

Then I get this error:

ExtendedSearchComponent.html:88 ERROR TypeError: Cannot read property 'apply' of undefined
    at filter (extended-search.component.ts:213)
    at ExtendedSearchComponent.push../src/app/participant/components/extended-search/extended-search.component.ts.ExtendedSearchComponent.searchFor (extended-search.component.ts:220)
    at Object.eval [as handleEvent] (ExtendedSearchComponent.html:91)
    at handleEvent (core.js:19628)
    at callWithDebugContext (core.js:20722)
    at Object.debugHandleEvent [as handleEvent] (core.js:20425)
    at dispatchEvent (core.js:17077)
    at core.js:17524
    at HTMLButtonElement.<anonymous> (platform-browser.js:993)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)

Oke, I did some debugging.

and put this:

 console.log('Method', method);

But then I see that multiple methods are been called:

Method filterByRegistration
extended-search.component.ts:214 Method filterByInlog
extended-search.component.ts:214 Method filterByChat

What of course not has to been. Just one api call at a time.

Upvotes: 0

Views: 992

Answers (3)

traktor
traktor

Reputation: 19301

The lastest version of code in the post calls filter six times when initializing const filters. However filter should only be called once in the if statement at the end of searchFor.

One way of achieving this is to record both the method name and parameters in the filters object and modify filter to pick up both the method and its parameters. For example:

function searchFor() {

  const filter = (using) => {
    this.extendedSearchService[using.method](...using.params).subscribe(filter => {
      console.log(using.method);
      this.filterparticipant.emit(filter);
    });
  };

  const filters = {
    Registratie: { method: 'filterByRegistration', params: [this.selectedValue, this.startDate]},
    Chat: { method: 'filterByChat', params: [this.startDate]},
    Inlog: { method: 'filterByInlog', params:  [this.startDate]},
    QrCode:{ method: 'filterByQrCodes', params: [this.selectedValue, this.startDate, this.selectedQrcode]},
    Doelen: { method: 'filerByChallenge', params: [this.selectedValue, this.startDate, this.selectedValueOptie, this.selectedValueProgressie]},
    Vcheq: { method: 'filterByVchecCode', params: [this.selectedValue, this.startDate, this.selectedVcheqOption]},
  }

  if (filters[this.selectedSearch]) {
    filter(filters[this.selectedSearch]);
  }
} 

Upvotes: 1

BBM
BBM

Reputation: 31

Made something dynamic, this way you avoid checking one by one

const filter = (method, params) => {
  this.extendedSearchService[method](...params).subscribe(filter => {
     this.filterparticipant.emit(filter);
  });
};

const filters = {
   Registratie: filter('filterByRegistration', [this.selectedValue, this.startDate]),
   Chat: filter('filterByChat', [this.startDate]),
   Inlog: filter('filterByInlog', [this.startDate]),
   QrCode: filter('filterByQrCodes', [this.selectedValue, this.startDate, this.selectedQrcode]),
   Doelen: filter('filerByChallenge', [this.selectedValue, this.startDate, this.selectedValueOptie, this.selectedValueProgressie]),
   Vcheq: filter('filterByVchecCode', [this.selectedValue, this.startDate, this.selectedVcheqOption]),
}

if(filters[this.selectedSearch]) {
   filters[this.selectedSearch]();
}

Upvotes: 0

George
George

Reputation: 6739

You could create an object with the property as the search type and the function as the value.

This is an example of how it works

var searchObject = {
  optionA: function(){
    console.log('Option A')
  },
  optionB: function(){
    console.log('Option B')
  }
}

function search(option){
  searchObject[option]()
}

search('optionA')
search('optionB')

And this is a snippet of what your code would look like, I haven't kept up with angular so it might be this.searchObject depending on where you define it, but the concept would be the same

var searchObject = {
  Registratie: function() {
    this.extendedSearchService
      .filerByRegistration(this.selectedValue, this.startDate)
      .subscribe(filterByRegistration => {
        this.filterparticipant.emit(filterByRegistration);
      });
  },
  Chat: function() {
    this.extendedSearchService.filterByChat(this.startDate).subscribe(filterByChat => {
      this.filterparticipant.emit(filterByChat);
    });
  }
}



searchFor() {
  searchObject[this.selectedSearch]()
}

Upvotes: 0

Related Questions