I'm trying to show the card info of South Africa as default value (before typing any country's name into the search bar input field or chosing a specific country out of a given list) and the according country info details within the card container! In this context, I'm using the restcountries api with their country json info! Why is it not working with 'forEach' and maybe you might have any ideas or suggestions how to solve it?

    beforeMount() {
        var self = this;
        var found = false;
        this.countries.forEach(function(element) {
          if(element['alpha2Code'] === 'ZA') {
            self.selectCountry(element);
            //self.push(element);
            found = true;
          }
        });      

        if(!found)
            this.selectCountry(this.countries[0]);
    
      },



html:
<main>

  <nav>
  <div id="app">
    <div class="country-search">
      <input type="text" placeholder="Search country..." autocomplete="off" v-model="search">
    </div>

    <div class="country-list" id="country-list">

      <div class="country" v-for="(country, index) in countries"  method="GET" @click="selectCountry(country)">
        <img :src="getFlagSrc(country)">
        {{ getName(country).common }}
      </div>

    </div>
  </nav>

  <section :style="{ 'background-image': url(' + selectedFlagSrc + ')' }" v-for="(country, index) in filteredCountries" @click="selectCountry(index)">

    <div class="card-container">
      <div class="card">

        <div class="card-title">
          <img :src="selectedFlagSrc.flags.png" alt="" />
        {{ selectedName.common }}
        </div>

        <div class="card-body">
          <div><strong>Code: </strong>{{ selectedCode }}</div>
          <div><strong>Capital: </strong>{{ selectedCapital }}</div>
          <div><strong>Region: </strong>{{ selectedSubregion }}</div>
          <div><strong>Language: </strong>{{ selectedLanguage }}</div>
          <div><strong>Currency: </strong>{{ selectedCurrency }}</div>
          <div><strong>Timezone: </strong>{{ selectedTimezone }}</div>
          <div><strong>Population: </strong>{{ selectedPopulation }}</div>
          <div><strong>Area: </strong>{{ selectedArea }}</div>
          <div><strong>World Bank Gini: </strong>{{ selectedGini }}</div>
          <div><strong>Lat Long: </strong><a :href="selectedLatlngUrl" target="_blank">{{ selectedLatlng }}</a></div>
</div>

      </div>
    </div>

  </section>

</main>

enter image description here

I hope to solve the issue with the default values!All around the card container on the right one should see the flag of South Africa as default bfore making any choice (respectively afterwards - the given flag of a chosen or country typed into the input field on the left in the picture below)! So far, the info concerning the chosen country haven't been correctly transferred to the card container on the right, unfortunately ;(!

2

There are 2 answers

1
B C On

So far, I've managed to solve the background topic, the one with the card container title repetition and could also return the vast majority of the card container values (with a mix of your and my code parts), except for the currencies and languages which are definitely more challenging in the v3.1 of restcountries api and I've to think about in more detail nowArgentina's Geodata Well, default value of South Africa (beforeMount) and the geodata info for currencies and languages are still missing and to elaborate on!

If anyone of the brain drain here had any suggestions or ideas how to cope with the remaining parts, I'd be more than grateful for any hints ;)!

For those of you who continuously like to train their brain and solve challenging tasks, I hereby provide you with my updated code (see codepen-link below )! As I'm well aware of the fact that it is by far not perfect I'm doing my best to improve and further elaborate on it !

5
duckstery On

I've manage to fix your code

There are a lot of problems in your code and there are still more. You really should check it out

HTML structrue

You've put the card outside of Vue app mounting target (the div id="app" inside your html). That's the reason why card only show {...}. Also, I have replace <div id="app"/> with <main id="app"/> because your CSS made the card overlay and cover the list.

  <main id="app">
    <nav>
      <div class="country-search">
        <input type="text" placeholder="Search country..." autocomplete="off" v-model="search">
      </div>
      <div class="country-list" id="country-list">
        <div class="country" v-for="(country, index) in filteredCountries" method="GET" @click="selectCountry(country, index)">
          <img :src="getFlagSrc(country)">
          {{ getName(country).common }}
        </div>
      </div>
    </nav>

    <section :style="`{background-image: url('${selectedFlagSrc}')}`">
      <div class="card-container">
        <div class="card">

          <div class="card-title" id="card_title" method="GET" v-if="selectedCountry" v-for="name in selectedCountry.name.common">
            <img :src="selectedFlagSrc" alt="" />
            {{ selectedCountry.name.common }}
          </div>

          <div class="card-body" id="card_body">
            <div><strong>Code: </strong>{{ selectedCode }}</div>
            <div><strong>Capital: </strong>{{ selectedCapital }}</div>
            <div><strong>Region: </strong>{{ selectedSubregion }}</div>
            <div><strong>Language: </strong>{{ selectedLanguage }}</div>
            <div><strong>Currency: </strong>{{ selectedCurrency }}</div>
            <div><strong>Timezone: </strong>{{ selectedTimezone }}</div>
            <div><strong>Population: </strong>{{ selectedPopulation }}</div>
            <div><strong>Area: </strong>{{ selectedArea }}</div>
            <div><strong>World Bank Gini: </strong>{{ selectedGini }}</div>
            <!--<div><strong>Lat Long: </strong><a :href="selectedLatlngUrl" target="_blank">{{ selectedLatlng }}</a></div>-->
          </div>
        </div>
      </div>
    </section>
  </main>

Moreover, you didn't close a lot of tags and misplace them. Like how you open <nav> before <div> but you close <nav> before <div>

Computed and hook

First, do not modify computed if you didn't declare setter for it. That's the reason why I deleted countries and changed it to data

Don't put your API call (ajax, fetch) inside computed properties. I've moved all logics inside computed.countries into your mounted. I also removed your filter mechanism, you'll need to re implement it in side mounted because I don't really understand how it worked. This is how your mounted look like

mounted() {
    (async () => {
      const response = await fetch("https://restcountries.com/v3.1/all");
      let countries = await response.json();
      countries.sort((a, b) => a.name.common.localeCompare(b.name.common));

     this.countries = countries;
      // After mount, pick South Africa as default

      for (let [i, country] of Object.entries(this.countries)) {
        if (country["name"]["common"] === 'South Africa') {
          this.selectCountry(country, i);

          return;
        }
      }

      this.selectCountry(this.countries[0], 0);
    })();
  },

I've also delete your beforeMount since it didn't do anything because you declared it inside methods and you didn't call it

Properties

You use some undeclared properties in HTML template like selectedFlagSrc

Methods

selectCountry require index to work. If index is null, the line below will fail

self.search = self.filteredCountries[index].name.common;

But you use it without providing index at mounted

this.selectCountry(this.countries[0])

There are still a lot to check. You should recheck your code before moving any further. Please be patient and coding with care.

Since you coding your Vue application like this, I suggest take a look at Vue document to create a native Vue project. Splitting chunk to component help you debug your code easier

This is the code after fix https://codepen.io/duckstery/pen/vYbmVmZ

Good luck to you