Передача массива в Handlebars Custom Helper

Я пытаюсь передать массив данных пользовательскому помощнику с помощью express-handlebars. Я не могу заставить его работать.

Я могу передать строку, и я могу передать массив отдельному представлению, но я не могу передать массив пользовательскому помощнику. Вот мой код:

Строка, переданная пользовательскому помощнику (это работает)

// app.js
const hbs = expressHandlebars.create({
  extname: 'html',
  helpers: {
    foo: function () {
      return 'FOO!'
    }
})

// views/layout/main.html
<h2>{{ foo }}</h2>

// Result --> FOO! outputed as expected

Передача массива в индивидуальное представление (это тоже работает)

// controllers/pageControllers.js
exports.getIndexPage = (req, res) => {
  res.render('index', {
    testList: ['one', 'two', 'three']
  })
}

// views/index.html
{{#each testList}}
<div>{{this}}</div>
{{/each}}

// Result --> one, two, three outputted as expected

Массив передан пользовательскому помощнику (это НЕ работает)

// app.js
const hbs = expressHandlebars.create({
  extname: 'html',
  helpers: {
    testList2: function () {
      return ['one', 'two', 'three']
    },
  }
})

// views/layout/main.html
{{#each testList2}}
  <div>{{this}}</div>
{{/each}}

// Result --> NOTHING.  No output, no error messages.

Пользовательские помощники не принимают массивы? Тот же код работает на отдельном представлении. Тот же код работает для строки в пользовательском помощнике. Это просто не работает для массива в пользовательском помощнике.

Если пользовательские помощники НЕ принимают массивы, то как я могу получить массив данных в свой основной файл макета? Если он принимает массив, то что я делаю неправильно и как заставить это работать?

Спасибо.


person Moshe    schedule 17.07.2020    source источник


Ответы (1)


Согласно documentation#helpers, я не использую express-handlebars сам< /эм>.

Вызов помощника Handlebars — это простой идентификатор, за которым следует ноль или более параметров (разделенных пробелом).

Это означает, что вы вызываете его с первым идентификатором, а то, что следует за ним, должно быть оценено.

Помощник просто принимает данные и выводит обработанный результат для вставки в представление.

Получение данных будет выглядеть примерно так: {{ foo exp1 exp2 }}, что переводится как {{foo(exp1,exp2)}}, и помощник будет выглядеть примерно так.

 foo: function (exp1, exp2) {
      return `this is ${exp1} and ${exp2}`
    }

Это похоже на вызов обычной функции.

В первом примере вы вызываете foo() (вспомогательную функцию), которая ничего не принимает, но выводит строку, и при активации вы получаете возвращаемое значение.

Во втором примере вы используете экспресс для рендеринга переменной, которая зацикливается в представлении. ничего общего с созданием экземпляра руля. (вы создаете в основном экспресс-переменную res.locals.testList.)

В третьем примере вы пытаетесь зациклить вспомогательную функцию, не вызывая ее на самом деле. Он пытается сделать что-то вроде этого:

for(let v of function() {}) {
 //...
}

Это выдаст ошибку (вероятно, тихую в вашем случае) is not iterable

Похоже, вы должны манипулировать массивом данных внутри вспомогательной функции, а затем возвращать строку или строку html (используя Handlebars.Safestring, как указано в документах для экранирования html). Затем, на ваш взгляд, просто назовите его {{ testList2 }}, который выведет готовый HTML для структуры, которую вы пытались сделать.

Надеюсь, это имеет смысл.

Тем не менее, существуют более продвинутые способы использования помощников, как указано в документации. которые, возможно, больше подходят для того, что вы пытаетесь сделать.

person fedesc    schedule 17.07.2020
comment
Спасибо за ваш ответ. Мне кажется, что мой настоящий вопрос - это вопрос Express.js, а именно, как передать данные в макет. - person Moshe; 17.07.2020
comment
Бекеф ахи. :) Это зависит от того, что вы пытаетесь сделать. res.render() предназначен для рендеринга шаблона (в HTML) с переменными представления (что вы пытаетесь сделать). Вы также можете использовать другие способы ответа на экспресс-запрос HTTP. если вы пытаетесь отправить ответы в формате json (res.json()/res.jsonp()) или просто выполняете простое перенаправление с помощью флэш-сообщения (res.redirect). res.render(). Нажмите на документы экспресс-ответа, чтобы узнать обо всех возможных вариантах - person fedesc; 17.07.2020
comment
Вот что я в итоге сделал: stackoverflow.com/a/62953247/7477670 - person Moshe; 17.07.2020
comment
@ Моше app.locals не для этого. правильный способ отправки переменных в представление — res.render(). - person fedesc; 17.07.2020
comment
@ Моше, я имел в виду res.locals. Не указано, что вы выполняете рендеринг с res.render() после app.locals. FWIW я ответил на возможное решение вопроса, который вы здесь указали. - person fedesc; 17.07.2020