AngularJS conditionally add a custom 'data-toggle' attribute - angularjs

I have the following directive:
myDirective.directive('sidebar', function () {
return {
restrict: 'E',
replace: true,
template: '<li ng-repeat="m in menu" ng-class="{\'dropdown\':m.submenu}">' +
'<a href="{{m.url}}" ng-class="{\'dropdown-toggle\':m.submenu}" ng-attr="{\'data-toggle=dropdown\': m.submenu">' +
'<i class="{{m.image}}"></i>' +
' {{m.name}}' +
'<b class="caret" ng-if="m.submenu"></b>' +
'</a>' +
'<ul ng-if="m.submenu" class="dropdown-menu">' +
'<li ng-repeat="s in m.submenu"><i class="{{s.image}}"></i> {{s.name}}</li>' +
'</ul>' +
'</li>',
link: function (scope, elem, attrs) {
scope.menu = [
{
"name": "Home",
"url": "/",
"image": "fa fa-bar-chart-o"
},
{
"name": "Data Integration",
"url": "/manage/dataintegration/index",
"image": "fa fa-dashboard"
},
{
"name": "Users",
"url": "/manage/users/index",
"image": "fa fa-dashboard"
},
{
"name": "Logger",
"url": "/manage/logger/index",
"image": "fa fa-dashboard"
},
{
"name": "Drop",
"url": "",
"image": "fa fa-dashboard",
"submenu": [
{
"name": "Logger",
"url": "/manage/logger/index",
"image": "fa fa-dashboard"
},
{
"name": "Logger2",
"url": "/manage/logger/index",
"image": "fa fa-dashboard"
}
]
}
]
}
}
});
I'm trying to get the data-toggle='dropdown' attribute to the a tag only if m.submenu exists using ng-attr but it doesn't work.

Assuming that's verbatim:
ng-attr="{\'data-toggle=dropdown\': m.submenu"
Is missing a closing }

As for me, ng-attr doesn't work at all, you can try this one
ng-attr-data-toggle="{{m.submenu && 'dropdown' || null}}"
but it will the attribute without the value even if m.submenu is false. Hope it will help.

Related

AngularJS Dropdown Multiselect adding custom button

I am currently stuck in a situation where I have to add a button to drop down options but can't find any help to add custom button to drop down options using this library
main.js
$scope.example14model = [];
$scope.example14settings = {
scrollableHeight: '200px',
scrollable: true,
enableSearch: true
};
$scope.example14data = [{
"label": "Alabama",
"id": "AL"
}, {
"label": "Alaska",
"id": "AK"
}
];
main.html
<div ng-dropdown-multiselect=""
options="example14data"
selected-model="example14model"
checkboxes="true"
extra-settings="example14settings"></div>
How can I add button to my drop down options? Any help will be highly appreciated.
I think this is what you are looking for :
https://jsfiddle.net/michaeldeongreen/22et6sao/9/
JS
'use strict';
var app = angular.module('myApp', ['angularjs-dropdown-multiselect']);
app.controller('AppCtrl', function ($scope) {
$scope.example14model = [];
$scope.example14settings = {
scrollableHeight: '200px',
scrollable: true,
enableSearch: true
};
$scope.example14data = [{
"label": "Alabama",
"id": "AL"
}, {
"label": "Alaska",
"id": "AK"
}, {
"label": "American Samoa",
"id": "AS"
}, {
"label": "Arizona",
"id": "AZ"
}, {
"label": "Arkansas",
"id": "AR"
}, {
"label": "California",
"id": "CA"
}, {
"label": "Colorado",
"id": "CO"
}, {
"label": "Connecticut",
"id": "CT"
}, {
"label": "Delaware",
"id": "DE"
}, {
"label": "District Of Columbia",
"id": "DC"
}, {
"label": "Federated States Of Micronesia",
"id": "FM"
}, {
"label": "Florida",
"id": "FL"
}, {
"label": "Georgia",
"id": "GA"
}, {
"label": "Guam",
"id": "GU"
}, {
"label": "Hawaii",
"id": "HI"
}, {
"label": "Idaho",
"id": "ID"
}, {
"label": "Illinois",
"id": "IL"
}, {
"label": "Indiana",
"id": "IN"
}, {
"label": "Iowa",
"id": "IA"
}, {
"label": "Kansas",
"id": "KS"
}, {
"label": "Kentucky",
"id": "KY"
}, {
"label": "Louisiana",
"id": "LA"
}, {
"label": "Maine",
"id": "ME"
}, {
"label": "Marshall Islands",
"id": "MH"
}, {
"label": "Maryland",
"id": "MD"
}, {
"label": "Massachusetts",
"id": "MA"
}, {
"label": "Michigan",
"id": "MI"
}, {
"label": "Minnesota",
"id": "MN"
}, {
"label": "Mississippi",
"id": "MS"
}, {
"label": "Missouri",
"id": "MO"
}, {
"label": "Montana",
"id": "MT"
}, {
"label": "Nebraska",
"id": "NE"
}, {
"label": "Nevada",
"id": "NV"
}, {
"label": "New Hampshire",
"id": "NH"
}, {
"label": "New Jersey",
"id": "NJ"
}, {
"label": "New Mexico",
"id": "NM"
}, {
"label": "New York",
"id": "NY"
}, {
"label": "North Carolina",
"id": "NC"
}, {
"label": "North Dakota",
"id": "ND"
}, {
"label": "Northern Mariana Islands",
"id": "MP"
}, {
"label": "Ohio",
"id": "OH"
}, {
"label": "Oklahoma",
"id": "OK"
}, {
"label": "Oregon",
"id": "OR"
}, {
"label": "Palau",
"id": "PW"
}, {
"label": "Pennsylvania",
"id": "PA"
}, {
"label": "Puerto Rico",
"id": "PR"
}, {
"label": "Rhode Island",
"id": "RI"
}, {
"label": "South Carolina",
"id": "SC"
}, {
"label": "South Dakota",
"id": "SD"
}, {
"label": "Tennessee",
"id": "TN"
}, {
"label": "Texas",
"id": "TX"
}, {
"label": "Utah",
"id": "UT"
}, {
"label": "Vermont",
"id": "VT"
}, {
"label": "Virgin Islands",
"id": "VI"
}, {
"label": "Virginia",
"id": "VA"
}, {
"label": "Washington",
"id": "WA"
}, {
"label": "West Virginia",
"id": "WV"
}, {
"label": "Wisconsin",
"id": "WI"
}, {
"label": "Wyoming",
"id": "WY"
}];
$scope.example2settings = {
displayProp: 'id'
};
});
var directiveModule = angular.module('angularjs-dropdown-multiselect', []);
directiveModule.directive('ngDropdownMultiselect', ['$filter', '$document', '$compile', '$parse',
function ($filter, $document, $compile, $parse) {
return {
restrict: 'AE',
scope: {
selectedModel: '=',
options: '=',
extraSettings: '=',
events: '=',
searchFilter: '=?',
translationTexts: '=',
groupBy: '#'
},
template: function (element, attrs) {
var checkboxes = attrs.checkboxes ? true : false;
var groups = attrs.groupBy ? true : false;
var template = '<div class="multiselect-parent btn-group dropdown-multiselect">';
template += '<button type="button" class="dropdown-toggle" ng-class="settings.buttonClasses" ng-click="toggleDropdown()">{{getButtonText()}} <span class="caret"></span></button>';
template += '<ul class="dropdown-menu dropdown-menu-form" ng-style="{display: open ? \'block\' : \'none\', height : settings.scrollable ? settings.scrollableHeight : \'auto\' }" style="overflow: scroll" >';
template += '<li ng-hide="!settings.showCheckAll || settings.selectionLimit > 0"><a data-ng-click="selectAll()"><span class="glyphicon glyphicon-ok"></span> {{texts.checkAll}}</a>';
template += '<li ng-show="settings.showUncheckAll"><a data-ng-click="deselectAll();"><span class="glyphicon glyphicon-remove"></span> {{texts.uncheckAll}}</a></li>';
template += '<li ng-hide="(!settings.showCheckAll || settings.selectionLimit > 0) && !settings.showUncheckAll" class="divider"></li>';
template += '<li ng-show="settings.enableSearch"><div class="dropdown-header"><input type="text" class="form-control" style="width: 100%;" ng-model="searchFilter" placeholder="{{texts.searchPlaceholder}}" /></li>';
template += '<li ng-show="settings.enableSearch" class="divider"></li>';
if (groups) {
template += '<li ng-repeat-start="option in orderedItems | filter: searchFilter" ng-show="getPropertyForObject(option, settings.groupBy) !== getPropertyForObject(orderedItems[$index - 1], settings.groupBy)" role="presentation" class="dropdown-header">{{ getGroupTitle(getPropertyForObject(option, settings.groupBy)) }}</li>';
template += '<li ng-repeat-end role="presentation">';
} else {
template += '<li role="presentation" ng-repeat="option in options | filter: searchFilter">';
}
template += '<a role="menuitem" tabindex="-1" ng-click="setSelectedItem(getPropertyForObject(option,settings.idProp))">';
if (checkboxes) {
template += '<div class="checkbox"><label><input class="checkboxInput" type="checkbox" ng-click="checkboxClick($event, getPropertyForObject(option,settings.idProp))" ng-checked="isChecked(getPropertyForObject(option,settings.idProp))" /> {{getPropertyForObject(option, settings.displayProp)}}</label></div></a>';
} else {
template += '<span data-ng-class="{\'glyphicon glyphicon-ok\': isChecked(getPropertyForObject(option,settings.idProp))}"></span> {{getPropertyForObject(option, settings.displayProp)}}</a>';
}
template += '</li>';
template += '<li class="divider" ng-show="settings.selectionLimit > 1"></li>';
template += '<li role="presentation" ng-show="settings.selectionLimit > 1"><a role="menuitem">{{selectedModel.length}} {{texts.selectionOf}} {{settings.selectionLimit}} {{texts.selectionCount}}</a></li>';
template += '</ul>';
template += '</div>';
element.html(template);
},
link: function ($scope, $element, $attrs) {
var $dropdownTrigger = $element.children()[0];
$scope.toggleDropdown = function () {
$scope.open = !$scope.open;
};
$scope.checkboxClick = function ($event, id) {
$scope.setSelectedItem(id);
$event.stopImmediatePropagation();
};
$scope.externalEvents = {
onItemSelect: angular.noop,
onItemDeselect: angular.noop,
onSelectAll: angular.noop,
onDeselectAll: angular.noop,
onInitDone: angular.noop,
onMaxSelectionReached: angular.noop
};
$scope.settings = {
dynamicTitle: true,
scrollable: false,
scrollableHeight: '300px',
closeOnBlur: true,
displayProp: 'label',
idProp: 'id',
externalIdProp: 'id',
enableSearch: false,
selectionLimit: 0,
showCheckAll: true,
showUncheckAll: true,
closeOnSelect: false,
buttonClasses: 'btn btn-default',
closeOnDeselect: false,
groupBy: $attrs.groupBy || undefined,
groupByTextProvider: null,
smartButtonMaxItems: 0,
smartButtonTextConverter: angular.noop
};
$scope.texts = {
checkAll: 'Check All',
uncheckAll: 'Uncheck All',
selectionCount: 'checked',
selectionOf: '/',
searchPlaceholder: 'Search...',
buttonDefaultText: 'Select',
dynamicButtonTextSuffix: 'checked'
};
$scope.searchFilter = $scope.searchFilter || '';
if (angular.isDefined($scope.settings.groupBy)) {
$scope.$watch('options', function (newValue) {
if (angular.isDefined(newValue)) {
$scope.orderedItems = $filter('orderBy')(newValue, $scope.settings.groupBy);
}
});
}
angular.extend($scope.settings, $scope.extraSettings || []);
angular.extend($scope.externalEvents, $scope.events || []);
angular.extend($scope.texts, $scope.translationTexts);
$scope.singleSelection = $scope.settings.selectionLimit === 1;
function getFindObj(id) {
var findObj = {};
if ($scope.settings.externalIdProp === '') {
findObj[$scope.settings.idProp] = id;
} else {
findObj[$scope.settings.externalIdProp] = id;
}
return findObj;
}
function clearObject(object) {
for (var prop in object) {
delete object[prop];
}
}
if ($scope.singleSelection) {
if (angular.isArray($scope.selectedModel) && $scope.selectedModel.length === 0) {
clearObject($scope.selectedModel);
}
}
if ($scope.settings.closeOnBlur) {
$document.on('click', function (e) {
var target = e.target.parentElement;
var parentFound = false;
while (angular.isDefined(target) && target !== null && !parentFound) {
if (_.contains(target.className.split(' '), 'multiselect-parent') && !parentFound) {
if (target === $dropdownTrigger) {
parentFound = true;
}
}
target = target.parentElement;
}
if (!parentFound) {
$scope.$apply(function () {
$scope.open = false;
});
}
});
}
$scope.getGroupTitle = function (groupValue) {
if ($scope.settings.groupByTextProvider !== null) {
return $scope.settings.groupByTextProvider(groupValue);
}
return groupValue;
};
$scope.getButtonText = function () {
if ($scope.settings.dynamicTitle && ($scope.selectedModel.length > 0 || (angular.isObject($scope.selectedModel) && _.keys($scope.selectedModel).length > 0))) {
if ($scope.settings.smartButtonMaxItems > 0) {
var itemsText = [];
angular.forEach($scope.options, function (optionItem) {
if ($scope.isChecked($scope.getPropertyForObject(optionItem, $scope.settings.idProp))) {
var displayText = $scope.getPropertyForObject(optionItem, $scope.settings.displayProp);
var converterResponse = $scope.settings.smartButtonTextConverter(displayText, optionItem);
itemsText.push(converterResponse ? converterResponse : displayText);
}
});
if ($scope.selectedModel.length > $scope.settings.smartButtonMaxItems) {
itemsText = itemsText.slice(0, $scope.settings.smartButtonMaxItems);
itemsText.push('...');
}
return itemsText.join(', ');
} else {
var totalSelected;
if ($scope.singleSelection) {
totalSelected = ($scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp])) ? 1 : 0;
} else {
totalSelected = angular.isDefined($scope.selectedModel) ? $scope.selectedModel.length : 0;
}
if (totalSelected === 0) {
return $scope.texts.buttonDefaultText;
} else {
return totalSelected + ' ' + $scope.texts.dynamicButtonTextSuffix;
}
}
} else {
return $scope.texts.buttonDefaultText;
}
};
$scope.getPropertyForObject = function (object, property) {
if (angular.isDefined(object) && object.hasOwnProperty(property)) {
return object[property];
}
return '';
};
$scope.selectAll = function () {
$scope.deselectAll(false);
$scope.externalEvents.onSelectAll();
angular.forEach($scope.options, function (value) {
$scope.setSelectedItem(value[$scope.settings.idProp], true);
});
};
$scope.deselectAll = function (sendEvent) {
sendEvent = sendEvent || true;
if (sendEvent) {
$scope.externalEvents.onDeselectAll();
}
if ($scope.singleSelection) {
clearObject($scope.selectedModel);
} else {
$scope.selectedModel.splice(0, $scope.selectedModel.length);
}
};
$scope.setSelectedItem = function (id, dontRemove) {
var findObj = getFindObj(id);
var finalObj = null;
if ($scope.settings.externalIdProp === '') {
finalObj = _.find($scope.options, findObj);
} else {
finalObj = findObj;
}
if ($scope.singleSelection) {
clearObject($scope.selectedModel);
angular.extend($scope.selectedModel, finalObj);
$scope.externalEvents.onItemSelect(finalObj);
if ($scope.settings.closeOnSelect) $scope.open = false;
return;
}
dontRemove = dontRemove || false;
var exists = _.findIndex($scope.selectedModel, findObj) !== -1;
if (!dontRemove && exists) {
$scope.selectedModel.splice(_.findIndex($scope.selectedModel, findObj), 1);
$scope.externalEvents.onItemDeselect(findObj);
} else if (!exists && ($scope.settings.selectionLimit === 0 || $scope.selectedModel.length < $scope.settings.selectionLimit)) {
$scope.selectedModel.push(finalObj);
$scope.externalEvents.onItemSelect(finalObj);
}
if ($scope.settings.closeOnSelect) $scope.open = false;
};
$scope.isChecked = function (id) {
if ($scope.singleSelection) {
return $scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp]) && $scope.selectedModel[$scope.settings.idProp] === getFindObj(id)[$scope.settings.idProp];
}
return _.findIndex($scope.selectedModel, getFindObj(id)) !== -1;
};
$scope.externalEvents.onInitDone();
}
};
}]);
HMTL
<div ng-app="myApp" ng-controller="AppCtrl">
<div ng-dropdown-multiselect="" options="example14data" selected-model="example14model" checkboxes="true" extra-settings="example14settings"></div> <pre>Selected Model: {{example14model}} | json</pre>

Generating forms dynamically using json schema with angularjs

I have a json schema which is something like below:
var schema = {
"type": "object",
"properties": {
"requestedFor": {
"type": "string"
},
"location": {
"type": "string"
},
"shortDescription":{
"type": "string"
},
"description": {
"type": "string"
}
}
};
var options = {
"fields": {
"requestedFor": {
"requestedFor": "text",
"label": "*Name"
},
"location": {
"type": "text",
"label": "*Location"
},
"shortDescription":{
"type": "text",
"label": "Short Description"
},
"description": {
"type": "textarea",
"label": "Description",
"rows": 5,
"cols": 60,
"label": "",
"wordlimit": 250
}
},
"form": {
"attributes": {
"method": "POST",
"action": "#",
"enctype": "multipart/form-data"
},
"buttons": {
"submit": {
"value": "Submit"
}
}
}
};
So i want to use this json schema to create a custom directive on the fly using angularjs. So for that i have created the code something like below:
var app = angular.module("app", [])
.directive("wrapper", function($compile, $interval) {
return {
scope: {
directiveName: "="
},
link: function(scope, elem, attrs) {
scope.$watch("directiveName", function() {
var html = "<" + scope.directiveName + "></" + scope.directiveName + ">";
elem.html(html);
$compile(elem.contents())(scope);
});
}
}
}).controller("addDirectives", function($scope, $interval) {
let directiveNames = ['d1', 'd2', 'd3', "d4"];
$scope.directiveName = directiveNames[0];
}).directive("d1", function() {
return {
template: "<input type='text'>Requested For</input>"
}
}).directive("d2", function() {
return {
template: "<input type='text'>Location</input>"
}
}).directive("d3", function() {
return {
template: "<input type='text'>Short Description</input>"
}
}).directive("d4", function(){
return {
template: "<input type='textarea'>Description</input>"
}
})
Here my intention is to use this json schema to generate the form dynamically because i have so many json files available so for that i need to create different custom directives.
<!DOCTYPE html>
<html ng-app="app">
<head>
<body ng-controller="addDirectives">
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="form"></div>
</div>
</div>
</div>
</body>
</html>
So can anybody provide any solution for this?

Getting out values from an array using angular.foreach in $scope

I have a dynamically changing array based on another code and I'm trying to retrieve specific data from the same.
Here is a sample of one dynamically generated array under $scope.filtereditem:
[{
"active": true,
"createdAt": "2015-10-05T20:19:58.264Z",
"desc": "With arugula, smoked almonds & chipotle vinaigrette",
"flavors": [{
"active": true,
"name": "Chocolate",
"price": 8
}, {
"active": false,
"name": "Strawberry",
"price": 8
}, {
"active": false,
"name": "Hazelnut",
"price": 8
}, {
"active": false,
"name": "Mint",
"price": 8
}],
"img": "https://signsrestaurant.ca/wp-content/uploads/2015/09/Watermelon-Quinoa-Jimaca-Salad.jpg",
"name": "Watermelon Quinoa Jicama Salad (<span class=\"vegan\">VE</span>, <span class=\"gfree\">GF</span>, <span class=\"dfree\">DF</span>)",
"objectId": "x1zpkWmvmP",
"price": 14,
"qty": 1,
"sides": [{
"active": false,
"name": "Soup"
}, {
"active": false,
"name": "Salad"
}, {
"active": false,
"name": "Fries"
}],
"sizes": [{
"active": false,
"name": "Small",
"price": 5
}, {
"active": true,
"name": "Medium",
"price": 10
}, {
"active": false,
"name": "Large",
"price": 15
}],
"type": "Soup",
"updatedAt": "2015-10-21T18:09:37.499Z"
}, {
"active": true,
"createdAt": "2015-10-05T20:35:01.363Z",
"desc": "Buffalo mozzarella, tomato, marinated artichoke hearts, black olives, pesto & balsamic drizzle",
"flavors": [{
"active": false,
"name": "Vanilla",
"price": 8
}, {
"active": false,
"name": "Almond",
"price": 8
}, {
"active": true,
"name": "Hazelnut",
"price": 8
}, {
"active": false,
"name": "Caramel",
"price": 8
}],
"img": "https://signsrestaurant.ca/wp-content/uploads/2015/09/Mediterranean-Salad.jpg",
"name": "Mediterranean Salad (<span class=\"veg\">V</span>, <span class=\"gfree\">GF</span>)",
"objectId": "nI5VSpdBUn",
"price": 15,
"qty": 2,
"sides": [{
"active": false,
"name": "Soup"
}, {
"active": false,
"name": "Salad"
}, {
"active": false,
"name": "Fries"
}],
"sizes": [{
"active": false,
"name": "Small",
"price": 0
}, {
"active": true,
"name": "Medium",
"price": 5
}, {
"active": false,
"name": "Large",
"price": 10
}],
"type": "Salad",
"updatedAt": "2015-10-21T18:09:33.422Z"
}]
That is just a sample and the array changes dynamically based on another code. What I wish to achieve is to retrieve certain data in the form of a scope element, let's name it as $scope.filteredmenu
This is where I'm stuck at. Here is what I have so far for this:
$scope.filteredmenu = function() {
var order = " ";
var side = " ";
angular.forEach($scope.filtereditem, function(item) {
var flavor = " ";
var size = " ";
order += item.name + "Qty: " + item.qty + " , ";
side += "Side: " + item.type + " , ";
angular.forEach(item.flavors, function(option) {
if (option && option.active) {
flavor += "Flavor: " + option.name + " , ";
}
});
angular.forEach(item.sizes, function(option) {
if (option && option.active) {
size += "Size: " + option.name + " , ";
}
});
menuorder += order + side + size + flavor;
});
return menuorder;
};
Basically, I need the output in this format:
For each item,
'item.name' Qty: 'item.qty', Side: 'item.type', Flavor (whichever is active): option.name (in item.flavors), Size (whichever is active): option.name (in item.sizes)
Eventually, I'm trying to send the result $scope.filteredmenu via an email API. I'm not sure what I'm doing wrong. Any help with this code would be much appreciated.
There were some syntax errors:
var output = function() {
var order = " ";
var side = " ";
//Not defined
var menuorder = '';
angular.forEach($scope.filtereditem, function(item) {
var flavor = " ";
var size = " ";
order += item.name + "Qty: " + item.qty + " , ";
//plus sign was missing
side += "Side: " + item.type + " , ";
angular.forEach(item.flavors, function(option) {
if (option && option.active) {
flavor += "Flavor: " + option.name + " , ";
}
});
angular.forEach(item.sizes, function(option) {
if (option && option.active) {
size += "Size: " + option.name + " , ";
}
});
menuorder += order + side + size + flavor;
});
return menuorder;
}
$scope.filteredmenu = output();
here is the working JSFiddler https://jsfiddle.net/hefc5ewe/

Doesn't show custom template with angularformly?

This is using angular-formly and i have created multiple-checkbox template as follows:
<script type="text/ng-template" id="multi-checkbox-template.html">
<div class="radio-group"
ng-class="{'has-error': options.formControl.$invalid}">
<label class="control-label">
{{options.label}}
{{options.required ? '*' : ''}}
</label>
<div class="radio"
ng-repeat="(key, option) in options.options">
<label>
<input type="checkbox"
formly-dynamic-name="id + '_'+ $index"
formly-custom-validation="options.validators"
id="{{id + '_'+ $index}}"
aria-describedby="{{id}}_description"
ng-value="option.value"
ng-required="options.required"
ng-model="$parent.model[$parent.options.key || $parent.index][option.name]">
{{option.name}}
</label>
<p id="{{id}}_description"
class="help-block"
ng-if="option.description">
{{option.description}}
</p>
</div>
</div>
</script>
This is config:
formlyConfigProvider.setType(
{
name: 'multi-checkbox',
templateUrl: 'multi-checkbox-template.html',
wrapper: ['bootstrapLabel', 'bootstrapHasError']
}
This is controller:
{
"key": "Q2",
"type":'multi-checkbox',
"templateOptions": {
"label": "What languages are you familiar with?",
"options": [
{ {
"name": "spanish",
"value": "spnsh"
},
{
"name": "french",
"value": "frnch"
},
{
"name": "more",
"value": "more"
}
]
}
}
];
Problem is that, doesn't show anything is the page even though error. I knew that path is correct regarding to the server response
`GET /multi-checkbox-template.html 200 1ms
This is warning i am getting,
angular-formly-bootstrap formly-field apiCheck failed! Required `label` not specified in `Argument 1/value/templateOptions`. Must be `String` https://github.com/formly-js/angular-formly/blob/6.10.0/other/ERRORS_AND_WARNINGS.md#formly-field-type-apicheck-failed
You passed:
{
"key": "Q2",
"type": "multi-checkbox",
"templateOptions": {
"to.label": "In what languages does your firm provide live chat support?",
"to.options": [
{
"name": "english",
"value": "eng"
},
{
"name": "spanish",
"value": "spnsh"
},
{
"name": "french",
"value": "frnch"
},
{
"name": "more",
"value": "more"
}
]
},
"$$hashKey": "object:592",
"data": {},
"validation": {
"messages": {}
},
"id": "formly_1_multi-checkbox_Q2_5"
}
With the types:
{
"key": "string",
"type": "string",
"templateOptions": {
"to.label": "string",
"to.options": {
"0": {
"name": "string",
"value": "string"
},
"1": {
"name": "string",
"value": "string"
},
"2": {
"name": "string",
"value": "string"
},
"3": {
"name": "string",
"value": "string"
}
}
},
"$$hashKey": "string",
"data": "Object",
"validation": {
"messages": "Object"
},
"value": "Function",
"runExpressions": "Function",
"resetModel": "Function",
"updateInitialValue": "Function",
"id": "string",
"initialValue": "undefined"
}
The API calls for:
{
"__apiCheckData": {
"strict": false,
"optional": false,
"type": "shape"
},
"shape": {
"templateOptions": {
"__apiCheckData": {
"strict": false,
"optional": false,
"type": "shape",
"error": "THIS IS THE PROBLEM: Required `label` not specified in `templateOptions`. Must be `String`"
},
"shape": {
"label": "String <-- YOU ARE MISSING THIS"
}
}
}
}
`
Please if there is any help i will be really thank you.
I think some of your references to options above should be referring to options.templateOptions instead (you can actually refer to this as to as a shortcut). For instance, options.label and options.options should be to.label and to.options. Not sure if this is the only issue though.
Also, the script tag business seems weird to me, but I always use:
template: require('path-to-my-template') and Webpack, so I can't be sure.
templateUrl in your formlyConfigProvider.setType() is not a directory link to your file.
the templateUrl is actually referring to the id attribute in your script tag
what you should do is:
formlyConfigProvider.setType(
{
name: 'multi-checkbox',
templateUrl: 'custom-template.html'
wrapper: ['bootstrapLabel', 'bootstrapHasError']
}
and in your template html file:
<script type="text/ng-template" id="custom-template.html">
<!-- your custom template should be here -->
</script>

How can I sort a directive output?

I have the following Directive:
app.directive('sidebar', function () {
return {
restrict: 'E',
replace: true,
template: '<li ng-repeat="(keymenu, valmenu) in menu"><i class="{{valmenu.image}}"></i><span class="hidden-sm">{{keymenu}}</span></li>',
link: function (scope, elem, attrs) {
scope.menu = {
"Home": {
"sort": 1,
"url": "/",
"image": "fa fa-bar-chart-o"
},
"Datasources": {
"sort": 2,
"url": "/datasources",
"image": "fa fa-dashboard"
},
"Logger": {
"sort": 3,
"url": "/Logger",
"image": "fa fa-dashboard"
}
}
}
}
});
Currently the order is: Datasources, Home, Logger I would like to order it either by the sort property or by it's 'natural' order as the elements are ordered within the scope.menu object.
You can use orderBy direcly into the <li /> template:
This code will sort your menu for the property name that you want:
'<li ng-repeat="(keymenu, valmenu) in menu| orderBy:myProperty">'
EDIT:
You should change the way your JSON looks, or you will have issues to access and order the menu. The way you did every menu entry is a different object, you should do like this:
scope.menu =[
{
"name": "Home",
"sort": 1,
"url": "/",
"image": "fa fa-bar-chart-o"
},
{
"name":"Datasources",
"sort": 2,
"url": "/datasources",
"image": "fa fa-dashboard"
},
{
"name": "Logger",
"sort": 3,
"url": "/Logger",
"image": "fa fa-dashboard"
}
]
Then sort by name for exemple:
'<li ng-repeat="(keymenu, valmenu) in menu| orderBy:name">'

Resources