Как сделать условный помощник с помощью ember-cli и handlebars 2.0.0?

Я пытаюсь добиться чего-то похожего на форму или функцию:

{{#if has-permission "my_permission"}}
    // do some stuff here
{{else}}
    // fallback
{{/if}}

OR

{{#hasPermission session.user.permissions "my_permission"}}

Я не могу понять это. Я прочитал это, но там мало что объясняется, кроме помощников, которые отображают контент или изменить его, например {{рендерить "что-то"}}

Когда я пытаюсь сделать это условным, я получаю следующее:

registerBoundHelper-generated helpers do not support use with Handlebars blocks.

Любая помощь очень ценится, спасибо!

РЕДАКТИРОВАТЬ:

Мой пользовательский объект сериализуется как таковой:

{"User": {
    "id": 3,
    "name": "john doe",
    "permissions": [
        "view_projects",
        "edit_milestones",
        "change_widgets"
    ]}
}

Я хочу иметь возможность проверять определенное разрешение в шаблоне, а не привязывать конкретное разрешение к вычисляемому свойству.

PS Я использую ember 1.9.1, последние данные и руль 2.0


person erichonkanen    schedule 04.02.2015    source источник


Ответы (2)


Согласно документам, это невозможно с привязанным помощником

Связанные помощники не поддерживают использование с блоками Handlebars или добавление дочерних представлений любого типа.

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

App.IndexController = Ember.ArrayController.extend({
  permission: "my_permission",
  hasPermission: function(){
    var permission = this.get('permission');

    return permission === 'my_permission';
  }.property('permission')
});

Затем в вашем шаблоне вы можете сделать:

<script type="text/x-handlebars" data-template-name="index">
  {{#if hasPermission }}

    <ul>
      {{#each item in model}}
        <li>{{item}}</li>
      {{/each}}
    </ul>

  {{ else }}
    // fallback
  {{/if}}
</script>

Рабочее решение здесь

person Kalman    schedule 04.02.2015
comment
Здравствуйте, спасибо за ответ. Я отредактировал свой вопрос выше. Мне нужно иметь возможность проверить, находится ли определенное разрешение в массиве User.permissions, поэтому в основном какой-то способ проверить это значение в [массиве] из шаблона. Существует свойство разрешений, которое представляет собой массив разрешений строкового значения, а не только одно единственное... - person erichonkanen; 04.02.2015
comment
Вы имеете в виду что-то вроде этого? emberjs.jsbin.com/hidoso/2/edit?html, js, консоль, вывод - person Kalman; 04.02.2015
comment
Интересно! Это действительно работает, и я могу в конечном итоге использовать это, так что спасибо. Мне все еще любопытно, возможно ли вообще что-то сделать, когда вы просто проверяете строку в шаблоне? - person erichonkanen; 04.02.2015
comment
См. следующее обсуждение некоторых альтернатив discuss.emberjs.com /t/ Я все еще думаю, что у меня самое чистое, но я предвзят;) - person Kalman; 04.02.2015

Вы можете использовать хелперы Ember по умолчаниюboundIf/unboundIf, чтобы создать хороший и мощный хелпер для управления разрешениями пользователей на стороне клиента и получить что-то вроде этого:

{{#can 'createPost'}}
    <button {{action newBlogPost}}>New Post</button>
{{else}}
    You don't have permission to post
{{/can}}

{{#each post in controller}}
    <a {{action viewPost post href=true}}>{{post.title}}</a>
    {{#can 'editPost' post}}
        <button {{action editPost post}}>Edit</button>
    {{/can}}
{{/each}}

Если вы посмотрите на исходный код и посмотрите, как работает if:

Ember.Handlebars.registerHelper('if', function(context, options) {
  Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2);
  Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop);

  return helpers.boundIf.call(options.contexts[0], context, options);
});

Вы можете видеть, что он выполняет только некоторую проверку работоспособности и передает boundIf:

Ember.Handlebars.registerHelper('boundIf', function(property, fn) {
  var context = (fn.contexts && fn.contexts[0]) || this;
  var func = function(result) {
  if (Ember.typeOf(result) === 'array') {
      return get(result, 'length') !== 0;
    } else {
      return !!result;
    }
  };

  return bind.call(context, property, fn, true, func, func);
});

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

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

Handlebars.registerHelper('can', function(permissionName, property, options){

  // do magic here

  Ember.Handlebars.helpers.boundIf.call(someObject, "someProperty", options)
}); 

Давайте подделаем магию и посмотрим, что произойдет:

Handlebars.registerHelper('can', function(permissionName, property, options){

  var permission = Ember.Object.create({
    can: function(){
      return true;
    }.property()
  });

  Ember.Handlebars.helpers.boundIf.call(permission, "can", options)
});

Хм, это оставляет содержимое скрытым. Кажется, что это не вызов может с нашего разрешения.

Если мы вернемся к boundIf, то увидим, что он просматривает контекст параметров и возвращается к this только в том случае, если нет ни одного набора:

var context = (fn.contexts && fn.contexts[0]) || this;

Мы можем обойти это, уничтожив контексты опций, которые мы передаем вboundIf. (Я не уверен, что это вызовет проблемы, но у меня это сработало… YMMV и все такое).

Handlebars.registerHelper('can', function(permissionName, property, options){

  var permission = Ember.Object.create({
    can: function(){
      return true;
    }.property()
  });

  // wipe out contexts so boundIf uses `this` (the permission) as the context
  options.contexts = null;

  Ember.Handlebars.helpers.boundIf.call(permission, "can", options)
});

Если вы поменяете результат can с истинного на ложное, мы увидим, что наш контент исчезает и снова появляется, успех!

Этот пример более подробно описан в отличном сообщение Ричарда Ливси

person Sávio Lucena    schedule 12.10.2015