Переплетенные переменные EJS и Javascript внутри <% тегов

Мне нужно использовать переменную Javascript (определенную в интерфейсе) в коде EJS следующим образом:

var selected = 1;
<% for (var i=0; i < supplies.length; i++) { %>
    if (i == selected) {
        console.log(supplies);    
    }
<% } %>

Я использую EJS, Express.js и socket.io. Я могу преобразовать переменную Javascript в переменную EJS, отправив сообщение на мой экземпляр сервера Node.js, но такой глупый... Есть ли способ использовать переменные Javascript внутри EJS?

EDIT: Я хочу получить доступ к ресурсам, массиву javascript, после того как пользователь выбрал элемент из выпадающего меню. Когда он выбирает этот элемент, функция javascript с вышеуказанным кодом должна получить доступ к некоторому EJS. Поэтому мне нужно использовать обычную Javascript-переменную в EJS.

Ответы

Ответ 1

Могу ли я передать переменную JavaScript в шаблон?:

Можно получить больше данных в шаблоне и повторно отобразить его, но не так, как вы думаете, и не делаете другого запроса на сервер (если только он не получит больше данных, а не получить больше HTML).

Решение:

Этот вопрос будет трудно ответить без каких-либо подробностей, поэтому я собираюсь сделать некоторые предположения о том, почему вы хотите передать выбранное значение в шаблон EJS. Я сделаю все возможное, чтобы ответить на это с ограниченной информацией о ваших целях.

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

Вот модифицированный шаблон cleaning.ejs, с добавленным классом с помощью помощника вида:

cleaning.ejs:

<script>
// NOTE: even if uncommented, JavaScript inside a template will not run.
//    var selected = 1;
</script>
<h1><%= title %></h1>
<ul>
    <% for(var i=0; i<supplies.length; i++) { %>

        <li>
            <!-- apply a class to the selected element -->
            <a class='<%= supplies[i].selected %>' href='supplies/<%= supplies[i].value %>'>
                <%= supplies[i].value %>
            </a>
        </li>
    <% } %>
</ul>    

Представленный HTML выглядит следующим образом:

<script>
    /** NOTE: Script blocks will not fire in rendered templates. They are ignored
    //    var selected = 1;
</script>
<h1>Cleaning Supplies</h1>
<ul>


        <li>
            <a class="" href="supplies/Broom">
                Broom
            </a>
        </li>


        <li>
            <!-- Note the selected element -->
            <a class="selected" href="supplies/mop">
                mop
            </a>
        </li>


        <li>
            <a class="" href="supplies/Hammer">
                Hammer
            </a>
        </li>

</ul>

Это представление было отображено с использованием следующего кода JavaScript:

// modified data structure so that array of supplies contains objects
 // with the name of the item and whether or not it selected.
data = {
    "title":"Cleaning Supplies",
    "supplies":[
        {
            "value":"Broom",
            "selected":""
        },
        {
            "value":"mop",
            "selected":"selected"
        },
        {
            "value":"Hammer",
            "selected":""
        }
    ]
};

// pass data into template and render
var html = new EJS({url: 'cleaning.ejs'}).render(data);

// add HTML to the DOM using a <div id="container"></div> wrapper.
document.getElementById("container").innerHTML = html;

Как вы можете видеть, при поставке [i].selected применяет выбранный класс к элементу, который был помечен как выбранный в структуре данных. Я изменил значение href так, чтобы он обратился к объекту в элементе i-го массива вместо значения самого массива.

Теперь, когда выбранный элемент изменен, мы просто модифицируем переменную данных, повторно визуализируем шаблон EJS и добавляем его в DOM.

С помощью этого CSS в заголовке вашего документа HTML вы увидите что-то похожее на то, что показано ниже:

<style>
    .selected { color:red; }
</style>

Demo of selected element in red


Почему JavaScript в шаблоне не запускается:

Метод, который вы пытаетесь использовать для управления значениями JavaScript или используете значения JavaScript внутри шаблона EJS, не будет работать. Это должно быть сделано в основном с учетом того, когда выполняется JavaScript.

Вы правы, думая, что шаблоны EJS скомпилированы на стороне клиента. Однако JavaScript в помощниках представления выполняется независимо от JavaScript в глобальном контексте. От взгляда на исходный код ejs.js кажется, что в процессе используется eval.

Кроме того, EJS возвращает отображаемый HTML как строку, а документация для EJS инструктирует нас вставлять эту визуализированную строку шаблона в DOM с помощью innerHTML:

document.getElementById("container").innerHTML = html;

Независимо от того, какую технологию просмотра вы используете, одна из основных истин некоторых браузеров, когда дело доходит до JavaScript, такова: Некоторые браузеры могут не оценивать блоки <script>, добавленные в DOM, используя innerHTML.

Другими словами, в моем тестовом шаблоне, когда я попытался добавить тэг script для вывода выбранного значения в консоль, я увидел, что блок script был добавлен, но из-за способа innerHTML работает, он не был выполнен:

Пример шаблона Демонстрирует, что JavaScript не будет запущен при добавлении с помощью innerHTML:

 <h1><%= title %></h1>
<ul>
    <% for(var i=0; i<supplies.length; i++) {  %>
       <span id="selected"></span><script>console.info('test <%= i %> = <%= supplies[i] %>');</script>            
        <li>
            <a href='supplies/<%= supplies[i] %>'>
                <%= supplies[i] %>
            </a>
        </li>
    <% } %>
</ul>

Выделенный HTML:

Как вы можете видеть ниже, операторы console.log присутствуют в HTML. Однако при добавлении с помощью innerHTML они не будут срабатывать.

Подход к технологиям просмотра - это ограничить их использование именно этим, создавая представление. Сохраняйте свою логику в "обычном JavaScript".

<h1>Cleaning Supplies</h1>
<ul>

       <span id="selected"></span><script>console.info('test 0 = Brrom');</script>            
        <li>
            <a href='supplies/Brrom'>
                Brrom
            </a>
        </li>

       <span id="selected"></span><script>console.info('test 1 = mop');</script>            
        <li>
            <a href='supplies/mop'>
                mop
            </a>
        </li>

       <span id="selected"></span><script>console.info('test 2 = Hammer');</script>            
        <li>
            <a href='supplies/Hammer'>
                Hammer
            </a>
        </li>

</ul>

Дополнительные примеры и документацию можно найти в шаблонах EJS на веб-сайте Google Code Embedded JavaScript.