I know this is a recurring question but unfortunately I couldn't find a proper answer to my case.
Basically I'm getting data from an JSON API endpoint which gets displayed in a table using ng-repeat
. I now want to ng-switch
the view to input fields for amending the data (and sending it later back to the server).
Atm, my solutions depends on having a property in the data which I don't really like. I'm sure there's a smarter way than injecting this property after having retrieved the data - any suggestions?
HTML:
<tbody>
<tr ng-repeat="item in data" ng-switch on="item.edit" >
<td ng-switch-default ng-bind="item.color"></td>
<td ng-switch-when='true'>
<input type="text" ng-model="item.color" />
</td>
<td ng-switch-default><button ng-click="switch(item)">edit</button></td>
<td ng-switch-when='true'><button ng-click="send(item)">send</button></td>
</tr>
</tbody>
JS:
var app = angular.module('myApp', []);
app.controller('MyCtrl', function($scope) {
$scope.switch = function (item) {
if (item.edit) {
item.edit = false;
} else {
item.edit = true;
}
};
$scope.send = function (item) {
if (item.edit) {
// data is sent...
item.edit = false;
} else {
item.edit = true;
}
};
$scope.data = [
{color: 'blue', edit: false},
{color: 'green', edit: false},
{color: 'orange', edit: false}];
});
thanks in advance!
here's a plunker: http://plnkr.co/edit/h8ar4S43JUvjHurzLgT0?p=preview
If you do not want to put your flags on your data objects than you will need to use a separate object to store them. With WeakMaps you can easily associate the data object, or the element itself, with a flags object. If you are targeting older browsers you will need to find a similar way to associate the data object / or element to the flags object
JS
let map = new WeakMap();
$scope.editing = function(item){
return map.get(item).edit;
}
$scope.switch = function (item) {
let flags = map.get(item);
if (flags.edit) {
flags.edit = false;
} else {
flags.edit = true;
}
};
//Note you could combine switch and send into a single toggle function
$scope.send = function (item) {
let flags = map.get(item);
if (flags.edit) {
flags.edit = false;
} else {
flags.edit = true;
}
};
$scope.data = [
{color: 'blue'},
{color: 'green'},
{color: 'orange'}
];
//Create an empty flags object for each data item
for(let item of $scope.data){
map.set(item,{});
}
HTML
<tr ng-repeat="item in data" ng-switch on="editing(item)" >
<td ng-switch-default ng-bind="item.color"></td>
<td ng-switch-when='true'>
<input type="text" ng-model="item.color" />
</td>
<td ng-switch-default><button ng-click="switch(item)">edit</button></td>
<td ng-switch-when='true'><button ng-click="send(item)">send</button></td>
</tr>
Demo
// Code goes here
var app = angular.module('myApp', []);
app.controller('MyCtrl', function($scope) {
var map = new WeakMap();
//Using fat arrow less code to write
$scope.editing = item=>map.get(item).edit;
//Since "switch" and "send" had similar
//toggling code just combined them
//Also no need to use if statement, just use the NOT operator
//to toggle the edit flag
$scope.toggle = item=>{
let flags = map.get(item);
flags.edit = !flags.edit;
};
$scope.switch = item=>{
$scope.toggle(item);
//Do some switching?
//if not doing anything else just
//call toggle in the ng-click
};
$scope.send = item=>{
$scope.toggle(item);
//Do some sending
};
$scope.data = [
{color: 'blue'},
{color: 'green'},
{color: 'orange'}];
for(let item of $scope.data){
map.set(item,{});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<table>
<thead>
<tr>
<th width="180">Column</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in data" ng-switch on="editing(item)" >
<td ng-switch-default ng-bind="item.color"></td>
<td ng-switch-when='true'>
<input type="text" ng-model="item.color" />
</td>
<td ng-switch-default><button ng-click="switch(item)">edit</button></td>
<td ng-switch-when='true'><button ng-click="send(item)">send</button></td>
</tr>
</tbody>
</table><br>
"$scope.data" should never change after hitting edit/send since the flag is no longer on the data item object:
<code><pre>{{data}}</pre></code>
</div>