AngularJS: динамическая пользовательская директива с несколькими шаблонами
Я Java-разработчик, работающий над сайд-проектом. Я решил использовать AngularJS, чтобы использовать мой RESTful веб-сервис.
Моя структура JSON выглядит следующим образом:
[
{
"generatorName": "name1",
"constructorParams": [
{
"type": "Boolean",
"value": "true",
},
{
"type": "Integer",
"value": "2",
}
]
},
{
"generatorName": "name2",
"constructorParams": [
{
"type": "Integer",
"value": "10",
},
{
"type": "Integer",
"value": "10",
}
]
}
]
Моя цель - отобразить конкретное (например, число, текст и т. Д.) Поле ввода на основе "типа" параметра конструктора и инициализировать его "значением". Итак, если был выбран первый генератор, я бы хотел что-то вроде этого:
<html>
<select>
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<input type="number" value="2">
<html>
Я прочитал некоторые темы и решил использовать пользовательскую директиву внутри моего цикла:
<p ng-repeat="param in selectedGenerator.constructorParams">
<constructor-param param="{{param}}"></constructor-param>
</p>
Вот моя пользовательская директива:
app.directive("constructorParam", function() {
return {
scope : {
param : '@'
},
templateUrl : '/html_templates/constructor_param_template.html'
};
});
И вот шаблон:
<div ng-switch="{{param.type}}">
<div ng-switch-when="Integer">
<input type="number" ng-attr-name="{{param.type}}" min="0" ng-attr-value="{{param.value}}">
</div>
<div ng-switch-when="Boolean">
<select ng-if="{{param.value}}" ng-attr-name="{{param.type}}">
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<select ng-if="!{{param.value}}" ng-attr-name="{{param.type}}">
<option value="true">Yes</option>
<option selected="selected" value="false">No</option>
</select>
</div>
<div ng-switch-when="String">
<input type="text" ng-attr-name="{{param.type}}" ng-attr-value="{{param.value}}">
</div>
<div ng-switch-when="Double">
<input type="number" ng-attr-name="{{param.type}}" step="0.01" min="0" ng-attr-value="{{param.value}}">
</div>
</div>
Это не работает. Я вижу в инструментах разработчика Chrome, что директива запущена, но она не дает видимых результатов. Мои вопросы:
1) Правильно ли я передал объект param в пользовательский элемент директивы?
2) я не уверен насчет scope
директивы - я также пытался param : '=param'
- это тоже не работает...
3) Как мне прочитать свойства переданного объекта в шаблоне? Я пробовал: value="{{param.type}}"
, value={{param.type}}
а также ng-attr-value="{{param.value}}"
, Ничто не работает, но это может быть совершенно другая причина...
4) Могу ли я использовать префикс "ng-attr-" для всех атрибутов HTML такого элемента, как имя и значение?
5) Код моего шаблона - это именно то, что я вставил - нужно ли мне сделать его правильной HTML-структурой с головой, телом и т. Д.? Должен ли я прикрепить <script>
с AngularJS? Я сделал это, но еще раз, без изменений.
6) Сценарий использования для всей истории состоит в том, чтобы выбрать конкретный генератор из раскрывающегося списка и отобразить его параметры конструктора указанным способом. Таким образом, он должен восстановить HTML с заменой генератора. Я предполагаю, что это сделано в цикле ng-repeat, но, пожалуйста, подтвердите это.
Большое спасибо за ваш вклад!:)
3 ответа
Прежде всего, спасибо вам обоим за помощь! К сожалению, я не могу пометить ни один из приведенных ответов как правильный, потому что мне приходится смешивать их, чтобы получить то, что я искал.
Я бы не стал здесь подробно останавливаться, позвольте мне поделиться с вами окончательным кодом:
<!-- container -->
<p ng-repeat="param in selectedGenerator.constructorParams">
<constructor-param param="param"></constructor-param>
</p>
<!-- template -->
<div ng-switch="param.type">
<div ng-switch-when="Integer">
<input type="number" name={{param.type}} min="0" value={{param.value}}>
</div>
<div ng-switch-when="Boolean">
<select ng-if="param.value" name={{param.type}}>
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<select ng-if="!param.value" name={{param.type}}>
<option value="true">Yes</option>
<option selected="selected" value="false">No</option>
</select>
</div>
<div ng-switch-when="String">
<input type="text" name={{param.type}} value={{param.value}}>
</div>
<div ng-switch-when="Double">
<input type="number" name={{param.type}} step="0.01" min="0" value={{param.value}}>
</div>
</div>
И вот директива, вы оба правильно поняли:
app.directive("constructorParam", function() {
return {
scope: {
param: '='
},
templateUrl: '/html_templates/constructor_param_template.html'
};
});
Еще раз - большое спасибо, я бы не решил эту проблему так быстро без вашей помощи!
Когда вы делаете param : '@'
это "привязка текста". Это полезно в том случае, если вы хотите указать Angular не интерпретировать то, что вы привязываете к своему атрибуту, как свойство в области, а как непосредственно строку.
Так что если вы сделаете
<my-custom-directive param="hello"></my-custom-directive>
Тогда в вашей директиве, param
будет равна строке "hello"
, Хотя, если вы связываете с param
используя двустороннюю привязку param : '='
то Angular будет искать hello
свойство в области видимости вместо того, чтобы принимать его как строковый литерал.
В вашем случае, когда вы делаете param="{{param}}"
Angular сначала распаковывает "param", просматривая область видимости, в строковый литерал, затем создает привязку. Так что, хотя это могло бы сработать, если param
была строка, в вашем случае это объект, поэтому я не думаю, что он будет играть хорошо. Так что я бы просто сделал прямую привязку к нему (см. Мой окончательный код ниже).
В вашем шаблоне директивы вы также используете несколько директив Angular, которые ожидают привязки области видимости, поэтому я бы попробовал связать без фигурных скобок. Смотрите мой пример кода ниже.
app.directive("constructorParam", function() {
return {
scope: {
param: '='
},
templateUrl: '/html_templates/constructor_param_template.html'
};
});
<!-- container -->
<p ng-repeat="param in selectedGenerator.constructorParams">
<constructor-param param="{{param}}"></constructor-param>
</p>
<!-- TEMPLATE -->
<div ng-switch="param.type">
<div ng-switch-when="Integer">
<input type="number" ng-attr-name="param.type" min="0" ng-attr-value="param.value">
</div>
<div ng-switch-when="Boolean">
<select ng-if="param.value" ng-attr-name="param.type">
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<select ng-if="!param.value" ng-attr-name="param.type">
<option value="true">Yes</option>
<option selected="selected" value="false">No</option>
</select>
</div>
<div ng-switch-when="String">
<input type="text" ng-attr-name="param.type" ng-attr-value="param.value">
</div>
<div ng-switch-when="Double">
<input type="number" ng-attr-name="param.type" step="0.01" min="0" ng-attr-value="param.value">
</div>
</div>
Если это все еще не работает, дайте мне знать, чтобы я мог попробовать это в CodePen.
1) Нет, вам нужно убрать фигурные скобки при передаче значений в директиву
<constructor-param param="param"></constructor-param>
2,3) в директивном использовании =
вместо @
, Так как @
принять строковое значение параметра и =
принять значение параметра
scope: {
param: '='
},
4) если вам нужно связать данные, используйте ng-model
вместо ng-attr
5) Вам не нужно добавлять html или тег body внутри constructor_param_template.html
шаблон.
6) это делает нг-повтор. как только массив обновится, он будет динамически обновлять DOM