I'm new to AngularJS. I have managed to generate the repeater field dynamically but I don't know how to save its value.
Repeater values come from an array in PHP. It would be something like this:
$repeater = [
'name' => 'redirections',
'title' => 'Redirection',
'add_button_text' => 'New redirection',
'save_button_text' => 'Save',
'delete_button_text' => 'Remove redirection',
'fields' => [
[
'name' => 'old_url',
'type' => 'url',
'label' => 'Old URL'
],
[
'name' => 'new_url',
'type' => 'url',
'label' => 'New URL'
]
]
];
Then the info I render in HTML like this:
<div class="field-container repeater">
<div class="field-wrapper" ng-repeat="(key, item) in repeaterItems">
<div class="title" ng-click="toggleRepeater($event)">
<span>{{ field.title }}</span>
<span ng-repeat="input in field.fields" class="field-block">
</span>
</div>
<div class="inside">
<div class="inputs" ng-repeat="(index, input) in field.fields">
<label>
{{ input.label }}
<input type="{{ input.type }}" name="{{ input.name }}"
value="{{ input.value }}" ng-model="input.value"
ng-change="update_repeater_item()">
</label>
</div>
<span class="delete"><span ng-click="remove_repeater_item($event)">
{{ field.delete_button_text }}
</span></span>
</div>
<input id="{{ item.id }}" class="{{ item.id }} repeater-item-value"
type="hidden" name="{{ field.name }}[{{ item.id }}][]" value="">
</div>
<button class="repeater-button add-button" ng-click="add_repeater_item($event)">
{{ field.add_button_text }}
</button>
<button class="repeater-button save-button" ng-click="save_repeater($event)">
{{ field.save_button_text }}
</button>
</div>
And finally, what I have about Angular is this:
scope.repeaterItems = [];
scope.toggleRepeater = function($event) {
const clicked = angular.element($event.currentTarget);
const inside = angular.element($event.currentTarget.nextElementSibling);
if (clicked.hasClass('open')) {
clicked.removeClass('open');
inside.removeClass('show'); // .inside
}
else {
clicked.addClass('open');
inside.addClass('show'); // .inside
}
};
scope.add_repeater_item = function() {
scope.repeaterItems.push({
'id': Date.now().toString(36) + Math.random().toString(36).substr(2),
'value': {}
});
};
scope.remove_repeater_item = function($event) {
const clicked = $event.currentTarget;
const container = clicked.closest('.field-wrapper'); // .field-wrapper
const inputs = container.getElementsByTagName('input');
let deletedItemId = '';
for (let input of inputs) {
if (input.type === 'hidden') {
deletedItemId = input.id;
}
}
scope.repeaterItems = $filter('filter')(scope.repeaterItems, {id: '!' + deletedItemId}, true);
};
scope.update_repeater_item = function(value) {
console.log(value);
};
scope.save_repeater = function($event) {
console.log($event);
};
What I get visually with this code is this (in case it helps): Repeater rendering
Any help or improvement of the current code is appreciated. Thanks.
Bind the inputs to properties of the ng-repeat item value object:
<div ng-repeat="item in repeaterItems" ng-init="itemIndex = $index">
<div ng-repeat="input in field.fields">
<label>
{{ input.label }}
<input type="{{ input.type }}" name="{{ input.name + itemIndex}}"
ng-model="item.value[input.name]"
ng-change="update_repeater_item(item, itemIndex, input.name)">
</label>
</div>
<span ng-click="remove_repeater_item(itemIndex)">
{{ field.delete_button_text }}
</span>
</div>
<button class="add-button" ng-click="add_repeater_item()">
{{ field.add_button_text }}
</button>
<button class="save-button" ng-click="save_repeater(repeaterItems)">
{{ field.save_button_text }}
</button>
This simplifies the code:
$scope.repeaterItems = [];
$scope.add_repeater_item = function() {
$scope.repeaterItems.push({
'id': Date.now().toString(36) + Math.random().toString(36).substr(2),
'value': {}
});
};
$scope.remove_repeater_item = function(index) {
console.log("removing", $scope.repeaterItems[index].id);
$scope.repeaterItems.splice(index,1);
};
scope.update_repeater_item = function(item, index, name) {
console.log(item.id, item.value);
console.log($scope.repeaterItems[index]);
console.log(name + ' changed to ' + item.value[name]);
};
$scope.save_repeater = function(items) {
console.log(items);
$http.post(url, items);
};