When using AngularJS ng-repeat with track by in my web application, when the view is updated the old view is still displayed together with the new view during 1 second or so.
The app displays this panel of alarms (it is a home assistant app). Alarms can be enabled, disabled or removed using the icon buttons:
When the user click the icon button in the middle, the view is updated to this:
But when the view is updated, during half a second or so, it is displayed the old view and the new view together at the same time:
Is this a expected behaviout using ng-repeat with track by?. The code in my html view is:
...
<tr ng-repeat= "alarm in GetAlarmsController.alarms track by alarm.getId()" >
<td class="text-right">
<span ng-switch="alarm.isEnabled()">
<button ng-switch-when="false" type="button" rel="tooltip" disabled class="btn btn-danger btn-icon btn-sm" >
<i class="fa fa-power-off"></i>
</button>
<button ng-switch-when="true" type="button" rel="tooltip" disabled class="btn btn-success btn-icon btn-sm" >
<i class="fa fa-power-off"></i>
</button>
</span>
</td>
<td class="text-right" ng-switch="alarm.isEnabled()">
<button ng-switch-when="false" type="button" rel="tooltip" class="btn btn-danger btn-icon btn-sm" ng-click="GetAlarmsController.enableAlarm(true, alarm.getId())">
<i class="fa fa-toggle-off"></i>
</button>
<button ng-switch-when="true" type="button" rel="tooltip" class="btn btn-success btn-icon btn-sm" ng-click="GetAlarmsController.enableAlarm(false, alarm.getId())">
<i class="fa fa-toggle-on"></i>
</button>
<button type="button" rel="tooltip" class="btn btn-danger btn-icon btn-sm" ng-click="GetAlarmsController.deleteAlarm(alarm.getId())">
<i class="fa fa-times"></i>
</button>
</td>
</tr>
...
And, in the JS controller:
...
self.getAlarms = function(){
AlarmAPIService.getAlarms()
.then(function(alarms) {
self.alarms = alarms;
},function() {
self.alarms = [];
})
}
...
const ALARMS_REFRESH_TIME_MS = 5000 ;
var refreshAlarmsInterval = $interval(self.getAlarms, ALARMS_REFRESH_TIME_MS);
...
...
self.enableAlarm = function(enable, alarmId){
enableString = (enable ? 'enabled' : 'disabled') ;
AlarmAPIService.enableAlarm(enable, alarmId)
.then(function() {
SweetAlertService.showSuccessAlert('Alarm ' + enableString + ' with success');
},function() {
SweetAlertService.showErrorAlert('Alarm could not be ' + enableString);
})
}
...
Though self.alarm is assigned to a new array of alarms objects in controller, I have checked that the id of this alarms objects remains the same (only changed its state, specifically the enabled state for the alarm enabled)
Related
I've been looking over JStree documents, but I can't seem to get these buttons to function permanently.
Please help, thank you.
JSP:
<div col-xs-12 id="button-row4">
<button class="btn btn-success btn-sm" id="delete_node" onclick="demo_create();">
<i class="glyphicon glyphicon-asterisk"></i>
Create
</button>
<button class="btn btn-warning btn-sm" onclick="demo_rename();">
<i class="glyphicon glyphicon-pencil"></i>
Rename
</button>
<button class="btn btn-danger btn-sm" onclick="demo_delete();">
<i class="glyphicon glyphicon-remove"></i>
Delete
</button>
</div>
<div id="jstree_demo_div"> *tree data list* </div>
Jquery:
$("#jstree_demo_div").jstree({
'core': {
'data': coredata
},
'search': {
"case_insensitive": true,
"show_only_matches" : true
},
'plugins': ["search"]
});
$('#jstree_demo_div').on("select_node.jstree",
function(evt, data){
console.log('id '+ JSON.stringify(data.node.id));
console.log('text '+ JSON.stringify(data.node.text));
console.log('li_attr '+ JSON.stringify(data.node.li_attr));
}
);
I want to call a JS function with an onClick attribute attached to a button within a Bootstrap popover like this :
$('[data-toggle="popover"]').popover({
trigger : 'click',
content : '<center><button onClick="quickDelete();return false;" name="dltBtn" class="btn btn-danger btn-xs btn-block"><i class="fa fa-trash"></i> Delete</button><button class="btn btn-warning btn-xs btn-block stsBtn"><i class="fa fa-edit"></i> Status</button></center>'
});
But when I click on the button :
ReferenceError: quickDelete is not defined
I also done that :
$('[data-toggle="popover"]').popover({
trigger : 'click',
content : '<center><button class="btn btn-danger btn-xs btn-block dltBtn"><i class="fa fa-trash"></i> Delete</button><button class="btn btn-warning btn-xs btn-block stsBtn"><i class="fa fa-edit"></i> Status</button></center>'
});
$('.dltBtn').click(function() {
alert('ok');
});
But nothing .. Can you help me maybe ?
Thank you so much !
I want to delete the criteria list item on clicking the delete button. Right now only the filter is getting refreshed. The tables are not being deleted. Suggestions to get through this.
HTML
<ul class="list-unstyled">
<li style="display: inline-block" ng-repeat="crtia in newCriteria" >
<table>
<tr>
<td>
<select class="input-sm" ng-model="crtia.name" ng-options="searchopt for searchopt in searchcriteria " ng-click="searchy.check()"></select>
</td>
<td>
<input class="input-sm " ng-model="crtia.value" placeholder="{{crtia.name}}" ng-change="newList()" ng-click="searchy.check()" />
</td>
<td>
<button type="button" class="btn btn-danger btn-xs" aria-label="Left Align" ng-click="removeCriteria($index)">
<span class="glyphicon glyphicon-remove" aria-hidden="true" ></span>
</button>
</td>
</tr>
</table>
</li>
</ul>
JS
$scope.removeCriteria=function($index){
$scope.searchy.check();
alert($index);
$scope.newCriteria.splice($index,1);
$scope.newList(); //Refreshes the filter
}
Try this
HTML
<button type="button" class="btn btn-danger btn-xs" aria-label="Left Align" data-ng-click="removeCriteria(crtia)">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
JS:
$scope.removeCriteria = function (sourceToRemove) {
$scope.searchy.check();
var index = $scope.newCriteria.indexOf(sourceToRemove);
$scope.newCriteria.splice(index, 1);
$scope.newList(); //Refreshes the filter
}
Update Plunker
As it is usually on any admin page I have 3 buttons next to each other. One for detail, one for edit and one for delete, it looks like:
<a n:href="detail $candidate->id">
<button type="button" class="btn btn-success btn-sm">
<i class="glyphicon glyphicon-search" style="margin-right:0px"></i>
</button>
</a>
<a href="#">
<button type="button" class="btn btn-info btn-sm">
<i class="glyphicon glyphicon-pencil" style="margin-right:0px"></i>
</button>
</a>
<a n:href="delete! $candidate->id">
<button type="button" class="btn btn-danger btn-sm">
<i class="glyphicon glyphicon-remove" style="margin-right:0px"></i>
</button>
</a>
After that I decide I need to add "Confirm modal" when user press "DELETE" to avoid missclicks
<a
data-nette-confirm="modal"
data-nette-confirm-title="Confirm"
data-nette-confirm-text="Are you sure you want to delete?"
data-nette-confirm-ok-class="btn-danger"
data-nette-confirm-ok-text="Yes"
data-nette-confirm-cancel-class="btn-success"
data-nette-confirm-cancel-text="No"
class="btn btn-danger"
data-ajax="off" // or class="ajax"
n:href="delete! $candidate->id">
<button type="button" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-remove" style="margin-right:0px"></i>
</button>
</a>
After this I just get my DELETE button twice that BIG as others, I try to just make it xs but still so much bigger. Is there a way how can I avoid this change?
Try removing:
// or class="ajax"
It overwrites previously defined class="btn btn-danger".
I have an ng-repeat which loops over some items, and am using an editmode parameter to switch between a label and inputfield to let the user edit the value in-line.
Now I would like the functionality to be like this:
when the user presses the Add button, a new empty (or default) item is created, that has the editmode set to true (so that the input textbox shows with the save button, rather than the label with the edit button).
I have googled a lot about this but could not find a clear answer so far. :(
Code is as follows:
<div ng-repeat="todo in todos">
<span data-ng-hide="editMode">
{{ todo.name }}
</span>
<input type="text" placeholder="{{ todo.name }}" data-ng-show="editMode" data-ng-model="name" data-ng-required />
<button type="submit" class="btn btn-default btn-xs" data-ng-hide="editMode" ng-click="editMode = true">
<span class="glyphicon glyphicon-edit"></span>
</button>
<button type="submit" class="btn btn-default btn-xs" data-ng-show="editMode" ng-click="editMode = false; editTodo(todo._id)">
<span class="glyphicon glyphicon-save"></span>
</button>
<button type="button" class="btn btn-default btn-xs" ng-click="deleteTodo(todo._id)">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
Thanks in advance
You could keep it simple by adding a separate input element outside of your ng-repeat.
Plunker: http://plnkr.co/edit/YDkzgtOSNpqDehnPkpZe?p=preview
Add another div element below your ng-repeat as below:
<div>
<button ng-show="!addNew" class="btn btn-sm btn-primary" ng-click="addNew=true">Add New</button>
<br>
<div ng-show="addNew">
<input type="text" ng-model="newTodo.name" ng-required />
<button type="submit" class="btn btn-default btn-xs" ng-click="addNewTodo()">
<span class="glyphicon glyphicon-ok"></span>
</button>
<button type="button" class="btn btn-default btn-xs" ng-click="resetNewTodo()">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
</div>
Don't use editMode as scope variable. Use it as todo's object field (todo.editMode). Set it to true for new todo object.
The ngRepeat offers you $index - current position, $first, $last - so you can check against those to determine when you're on the first or when you reached the last element.