2
  • when I console.log(feelings) it prints the inputted text value in the form.

  • However when I try to add 'feelings' to the object and update the ui with it I get [object Object]

  • when you use feelings.value down in the async code it works just fine. isn't feelings.value === .value.value??

<div class ="holder zip">
    <label for="zip">Enter Zipcode here</label>
    <input type="text" id="zip" placeholder="enter zip code here">
  </div>
  <div class ="holder feel">
    <label for="feelings">How are you feeling today?</label>
    <textarea class= "myInput" id="feelings" placeholder="Enter your feelings here" rows="9" cols="50"></textarea>
    <button id="generate" type = "submit"> Generate </button>
  </div>

    function generate (e) {
      const zipcode = document.querySelector('#zip').value;
      const feelings = document.querySelector('#feelings').value;
      console.log(zipcode)
      console.log(feelings)
    
      getWeather(baseURL+zipcode+apiKey)
      .then(function(data){
        postData(data)
      })
      .then(updateUI)
    }
    /* Function to GET Web API Data*/
    const getWeather = async (url = '') => {
      const response = await fetch(url);
    
      try {
        const weatherData = await response.json();
        weatherData['date'] = newDate; 
        weatherData['feelings'] = feelings; //where it displays as an {} unless use feelings.value
        console.log(weatherData);
        return weatherData;
    
      } catch(error){
        console.log('error', error);
      }
    }



  • Excuse me, its only working when I used... – Chris Cunningham Jun 30 '20 at 00:54
  • const feelings = document.querySelector('#feelings'); and then further down i use feelings.value – Chris Cunningham Jun 30 '20 at 00:54
  • it is not however working when i just use const feelings = document.querySelector('#feelings').value ; and then further down I just try to use 'feelings' and it returns [object Object] – Chris Cunningham Jun 30 '20 at 00:55
  • `feelings` in `getWeather` is not in the same scope as the code within `generate`, so it defaults to `window.feelings` since you don't have it scoped off, which in most Browser's will be the same as `document.getElementById('feelings')`. Don't use that first syntax when accessing Elements by HTML id in the real world. – StackSlave Jun 30 '20 at 00:56
  • 1
    oh man, haha thank you! yes this is totally a silly mistake. You are saying document.getElementByID('feelings') > document.querySelector('#feelings') ? thanks again – Chris Cunningham Jun 30 '20 at 01:08
  • 1
    @ChrisCunningham no, `document.getElementByID('feelings')` is the same as `document.querySelector('#feelings')`. The problem is that your browser already created a variable called `feelings` which is the dom element – ibrahim mahrir Jun 30 '20 at 01:12
  • The thing about keeping it local in this case is that the Element is gotten every time `generate` fires. Why get the Element again and again, when you can just get it once?... and *NO* on your question @ChrisCunningham, I'm saying `feelings` by itself is the same as those. – StackSlave Jun 30 '20 at 01:15

1 Answers1

2

feelings is not just any random object, it's your textarea element. This weird behavior is a bad feature of chrome and some other browsers; they assign DOM elements with ids to global variables named after the ids, read more about it on this other SO question: Do DOM tree elements with ids become global variables?

Since you're not passing feelings from generate to getWeather, the feelings used is the global variable created by the browser which is the DOM element, an object. In other words, the global variable feelings is not shadowed, so it is used.

To fix this, simply pass feelings as an argument from generate to getWeather like so:

function generate (e) {
  //...
  getWeather(baseURL + zipcode + apiKey, feelings)
  // ...
}

const getWeather = async (url, feelings) => {
  // here the parameter 'feelings' is used rather than the global variable 'feelings'.
}
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
  • Personally, I would just put `const feelings = document.querySelector('#feelings');` above `generate`, unless the Element has some kind of dynamic constraints. – StackSlave Jun 30 '20 at 01:07
  • @ChrisCunningham You're welcome! Glad I could help : ) – ibrahim mahrir Jun 30 '20 at 01:08
  • 1
    @StackSlave keeping things local is better, no need to pollute the global scope. Besides, `generate` is probably used as an event listener, so caching the value won't work as expected – ibrahim mahrir Jun 30 '20 at 01:10
  • yes, so actually when I jsut moved it to global scope some weird behavior was happening again, and I think this is why I moved it into generate in the first place – Chris Cunningham Jun 30 '20 at 01:12
  • 1
    @ChrisCunningham exactly. You should keep it inside and pass it as an argument like I showed you – ibrahim mahrir Jun 30 '20 at 01:14
  • 1
    Oh my gosh this is so relieving, so what youre saying is the feelings.value originally wasnt even using the feelings I had declared, it was using the one the browser created globally, and the name was coincidentally the same name as my declaration so it was hiding its origin from me! – Chris Cunningham Jun 30 '20 at 01:19
  • 1
    @ChrisCunningham yes – ibrahim mahrir Jun 30 '20 at 01:22
  • 1
    Oops, I thought I posted this here: The thing about keeping it local in this case is that the Element is gotten every time generate fires. Why get the Element again and again, when you can just get it once? – StackSlave Jun 30 '20 at 01:27
  • 1
    @StackSlave I just noticed that you didn't use `.value` in your comment, I thought you're storing the value. Caching the element totally makes sense, although nowadays, it hardly makes a difference because everything happens so fast anyway. – ibrahim mahrir Jun 30 '20 at 01:49