Как создать текстовое поле для автоматического ввода html, которое будет отображать значения, извлекаемые из API? - PullRequest
0 голосов
/ 07 сентября 2018

Я хочу создать текстовое поле ввода, в котором при щелчке будет показан список значений, извлекаемых через содержательный API. Код, кажется, не работает, когда он достиг цикла forEach. Работает нормально до initArray. Цикл forEach, похоже, не работает. Я вижу все свои данные в файле console.log файла initArray.

Я что-то упустил?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <title> URL Builder </title>
    <link rel="stylesheet" href="https://contentful.github.io/ui-extensions-sdk/cf-extension.css">
		<script src="https://unpkg.com/contentful-ui-extensions-sdk@3"></script>
  </head>
  <body>
    <form id="urlSearchContainer">
      <div class="cf-form-field">
        <input list="urlDataList" type="search" placeholder="Type your url here..." id="urlBuilder" class="cf-form-input">
        <datalist id="urlDataList">
        </datalist>
      </div>     
    </form>
    
    <script>
      "use strict"
      
      window.contentfulExtension.init(function(api) {
        api.window.startAutoResizer();
        
        // Set variables
        var urlDataList = document.getElementById("urlDataList");
        var urlInput = document.getElementById("urlBuilder");
                     
        function getUrlData(){
        //api.space.getEntries({'content_type[ne]': 'page-MBH'})
          var urlDataArray = [];
          api.space.getEntries()
          .then(function (entries) {
          	entries.items.forEach(function (entry) {
              if(entry.fields.url){
                var urlData = entry.fields.url.en
                urlDataArray.push(urlData);
                //console.log('urldata', urlDataArray);
              }
        	})
        })
          return urlDataArray;
        };
                
        function createUrlDropdown(){
          
          // Init data obj
          var data = getUrlData();
          var initArray = typeof data === 'object' && data instanceof Array && data.length > -1 ? data : [];
          
          console.log('ARRAY:: ', initArray);
          
          //Create and append url data list
          initArray.forEach(function(item) {
             console.log('item:: ', item);

            //Create a new <option> element.
            var option = document.createElement('option');
            console.log('option', option);
            
        		option.value = item;
            console.log('value', option);
            
        		// Add the <option> element to the <datalist>.
        		urlDataList.appendChild(option);
          });
          
          for(i = 0; i < initArray.length; i++) {
            console.log('obj');
            var option = document.createElement("option");
            option.value = initArray[i];
            
            urlDataList.appendChild(option);
  				}
				}          
        document.getElementById("urlBuilder").addEventListener("click", function(){
  				createUrlDropdown();
				});
      });
    </script>    
  </body>
</html>
  

Любая помощь приветствуется !!

1 Ответ

0 голосов
/ 07 сентября 2018

??

Проблема в функции getUrlData. api.space.getEntries возвращает обещание, которое вы правильно используете с then. Дело в том, что с обещаниями они асинхронны (как и многие другие в javascript).

То есть вы инициализируете urlDataArray и делаете вызов содержательному. И вы заполняете этот массив, когда вызов возвращается. Дело в том, что getUrlData уже вернул пустой массив.

    function getUrlData(){
      var urlDataArray = [];
      api.space.getEntries()
      .then(function (entries) {
        // this part is executed async
        entries.items.forEach(function (entry) {
          if(entry.fields.url){
            var urlData = entry.fields.url.en
            urlDataArray.push(urlData);
          }
        })
    })
      return urlDataArray;
    };

Лучший способ приблизиться к этому ИМО, чтобы изменить getUrlData и вернуть обещание.

function getUrlData() {
  // return this promise
  return api.space.getEntries()
    .then(function(entries) {
      // there is no need for another array
      // you can use map to grab the data you need
      return entries.items.map(function(item) {
        // map all the entries to the url strings
        return item.fields.url.en;
      })
    })
}

getUrlData()
  // only execute this when the data is there
  .then(function(urls) { console.log(urls); })

Ваш код выполняется в UI-расширении, но я также быстро изменил ваш код в codepen . Он использует Contentful CDA, но принципы остаются теми же.

Надеюсь, это поможет. :)

...