So in a normal table, I have this directive:
app.directive('highlightOnChange', function () {
return {
link: function (scope, element, attrs) {
attrs.$observe('highlightOnChange', function (val) {
element.addClass('flight-item-highlighted');
setTimeout(function () {
element.removeClass('flight-item-highlighted');
}, 300);
});
}
};
});
this works fine when used like this in an table:
<td highlight-on-change="{{value}}" ng-repeat="(key,value) in items"></td>
The idea is to highlight the specific cell once it is updated. This is needed because it is a realtime application, meaning changes will come from the server and needs to be highlighted when changed to let the user know.
But now I am using Angular UI-Grid which lazy loads the data (which is nice for performance) but not so nice for this feature.
I was able to implement it by defining a cell template:
<div class="ui-grid-cell-contents" highlight-on-change="{{grid.getCellValue(row, col)}}">{{grid.getCellValue(row, col)}}</div>
put it in the options:
$scope.tableColumns = [
{ field: 'name', displayName: 'Firstname', width:100, visible: true, cellClass: self.cellClass, cellTemplate: '/Templates/gridcelltemplate.html' },
{ field: 'gender' }, { field: 'company' }];
$scope.gridOptions = {
data: self.data,
columnDefs: self.tableColumns,
enableColumnResizing: true,
enableColumnMenus: false,
rowTemplate: '/Templates/rowtemplate.html',
headerTemplate : '/Templates/headertemplate.html',
};
But the result is that elements are always highlighted on scroll, obviously because they are created at that point (It does work nice for a single update though).
So one solution that I think of would be to change the css class from the controller for a specific column when the data has changed. But because the index will change on scroll for a particular row it would not make any sense. (Because row indexes are always from 0 to x, where x is the last shown row).
Another solution I can do is to keep the same directive, give a function that would call my controller. Controller would somehow need to check if the value is new or not and if so return true. Which would then result in an highlight.
inside directive:
....
scope: {
changed: '&',
},
link: function (scope, element, attrs) {
attrs.$observe('highlightOnChange', function (val) {
//now observed value of column, it has changed, call controller to check if it is a new value
var result = scope.changed({ val: val });
....
html template:
<div class="ui-grid-cell-contents" highlight-on-change="{{grid.getCellValue(row, col)}}" changed="grid.appScope.columnChanged(val)">{{grid.getCellValue(row, col)}}</div>
To be honest, I rather have lazy loading disabled, that would solve a lot of problems actually.
Edit:
Well, I found by setting gridOptions.virtualizationThreshold: self.data.length the lazy loading is disabled. But of course this comes with some major performance issues (having about 20 columns, 1000 rows). So perhaps an more elegant way would be nice :)
Related
I currently have the following code:
<div class="carousel" ng-if="novedadesEmpleados.cumpleanosDeHoy.length">
<div ng-repeat="empleado in novedadesEmpleados.todaysBirthdays" carousel-renderer class="event-card">
<birthday-card empleado="empleado" card-notifier></birthday-card>
</div>
</div>
Which used to work fine until I changed from using Bootstrap Carousel to Tiny Slider.
The array currently has 2 elements in it, however the HTML is rendering 6, 4 oh which are just showing the default angularjs text (name of properties in curly brackets) and the other 2 are displaying the correct information.
What could be causing this? The two directives are used to call the Tiny Slider initializer after they're done rendering:
angular.module('PortalIntranet').directive('cardNotifier', function ($timeout) {
return function(scope, element, attrs){
if(scope.$last)
scope.$emit('FinishedRendering');
}
});
angular.module('PortalIntranet').directive('carouselRenderer', function ($timeout) {
return function (scope, element, attrs) {
scope.$on('FinishedRendering', function (event) {
var slider = tns({
container: '.card-slider',
autoplay: true,
slideBy: 'page',
autoplayTimeout: 3500,
speed: 750,
autoplayButton: false,
nav: false,
autoplayButtonOutput: false,
controls: false
});
console.log(slider);
});
}
});
Angular is not likely displaying more items then are in the array. First, make sure your data is clean.
I believe the root ;) of your problem is in the directives and the rootScope. Most likely you need have the check when the condition is met on the rootScope or scope of the "carouselRenderer" not on the scope of the "cardNotifier". i.e.
if (scope.$parent.$last)
You want the last of the repeated items in the parent scope.
Also, as a side note, make sure your css classes are in the right place. Why is the "event-card" on the carousel-renderer and not on the birthday-card?
I was having a look at the adpt-strap table lite and was playing around with it. here is the JSfiddle that I was playing about with: http://jsfiddle.net/cx5gm0sa/
What I was trying to do and I was wondering if it is possible is to try and dynamically hide/show a column. The code I have added consists of $scope.showColumn = true; (you can see the value of this on the html page, I am printing it out at the top).
When you click the buy button on any row the variable gets set to the opposite of what it was before so it alternates between true and false.
$scope.buyCar = function (car) {
$scope.showColumn = !$scope.showColumn
};
This variable is also what is used for the visible property of the model column, however when the variable changes the column doesn't hide/show as I would have expected, it only ever seems to hide/show depending on what value the variable was initialized with. Is there anyway to make this work dynamically as I originally expected it would have and does anyone know why it wouldnt be working that way already?
Thanks in advance for any help I may get.
Got it. OK, I think the reason the table does not update is because your controller does not re-run the code that defines the table when you click the Buy button. I have changed this so that instead of assigning the array of the configs to the $scope.carsTableColumnDefinition directly, I defined a function named getDefinition that returns the array instead. Then in the $scope.buyCar = function (car){}, I then call the function.
So here are the changes I made:
$scope.carsTableColumnDefinition = getDefinition();
...
//Then inside the buyCar function I have:
$scope.buyCar = function (car) {
$scope.showColumn = !$scope.showColumn;
//now refresh by calling the get-definition function:
$scope.carsTableColumnDefinition = getDefinition();
};
..
//Finally, this is my getDefinition function:
function getDefinition(){
return [
{
columnHeaderDisplayName: 'Model',
displayProperty: 'name',
sortKey: 'name',
columnSearchProperty: 'name',
visible: $scope.showColumn
},
{
columnHeaderTemplate: '<span><i class="glyphicon glyphicon-calendar"></i> Model Year</span>',
template: '<strong>{{ item.modelYear }}</strong>',
sortKey: 'modelYear',
width: '12em',
columnSearchProperty: 'modelYear'
},
{
columnHeaderTemplate: '<span><i class="glyphicon glyphicon-usd"></i> Price</span>',
displayProperty: 'price',
cellFilter: 'currency',
sortKey: 'price',
width: '9em',
columnSearchProperty: 'price'
},
{
columnHeaderDisplayName: 'Buy',
templateUrl: 'src/tablelite/docs/buyCell.html',
width: '4em'
}
];
}
I updated the jsfiddle - check it out.
I'm trying to figure out how to get rid of an empty white space that shows up in my drop down menu. There was an "All" option that was not supposed to be in the menu. I got rid of that option (probably not the right move), and sometimes when I refresh I can see the menu and there's a white space and other times it just gives me an error on the console. I'm not sure why this variety exists.
Ultimately, I have to get rid of the All option (the right way) and remove a white space that it leaves.
Here is my js:
define(["app",
"lodash",
"service/reference",
"directives/control/topic-input"
], function (app) {
return app.directive('roleSelect', ['Reference', function (Reference) {
return {
restrict: 'A',
scope: {
selectedRole: '=',
selectedTopics: '=?',
presetRole: '=?',
topicNameOnly: '#?',
notUsePresets:'#?'
},
link: function ($scope, elem, attr) {
$scope.talentRoles = [];
$scope.topicNameOnly = ($scope.topicNameOnly === 'true');
$scope.notUsePresets = ($scope.notUsePresets === 'true');
if(!$scope.presetRole) {
$scope.presetRole = {id: -1, code: "ALL", description: "All"};
} // this is where the 'All' option comes from, so I just got rid of this if statement. Not sure if this is the right thing to do
if(!$scope.notUsePresets) {
$scope.talentRoles.push($scope.presetRole);
}
Reference.getTalentRoles($scope, function (response) {
$scope.talentRoles = response.concat($scope.talentRoles);
for(var i = 0;i<$scope.talentRoles.length;i++){
if($scope.selectedRole && $scope.selectedRole.description == $scope.talentRoles[i].description){
$scope.selectedRole = $scope.talentRoles[i];
}
}
});
$scope.showTopics = function(){
return attr.selectedTopics
}
$scope.roleChanged = function(role) {
$scope.selectedTopics = [];
};
},
templateUrl: '/directives/control/role-select.html'
};
}])
});
And here is my html:
<select class="form-control" required
id="roleSelector"
ng-options="talentRole as talentRole.description for talentRole in talentRoles track by talentRole.id" id="talentRole"
ng-change="roleChanged(role)"
ng-model="selectedRole">
<option ng-if="true" selected="true" value="" class="select-placeholder"><ln code="directive.role.select.tooltip" args=""></ln></option>
</select>
<div topic-input
name-only="topicNameOnly"
class="row-spacing"
ng-show="showTopics()"
ng-model="selectedTopics"
talent-role-id="selectedRole.id"></div>
I'm not too familiar with angular JS/ html. However, I do understand that the <option> </option> tag ensures that whatever was chosen from the user side stays selected on my side (as an admin). So, that functionality needs to remain. I also understand that ng-options is the mother of this menu. So perhaps there needs to be some configuration with this tag.
Here is a snapshot before deleting the if statement from the JavaScript:
It seems that when I delete the if statement, I get this error on the console:
TypeError: Cannot read property 'description' of undefined
So, I'm guessing getting rid of that condition is not the right thing to do. I apologize if I have not given enough, but please let me know what I can do to help you to help me further and I will be more than glad to accommodate.
I think you should remove presetRole: '=?' from your $scope initialization too if you remove the if.
Also, you need to check for any other references to presetRole, as it seems that even if you remove the if, the presetRole is still added to talentRoles.
Tell me if it worked.
Here i created same directive for wijmo grid, here my problem is i am not able to get selected row value,how to do section changed in directive ?
Thanks in advance
sample code for wijmo grid
app.directive('customFlexGrid', function ($compile) {
return {
restrict: 'E',
template: '<div/>',
replace: true,
scope: {
itemsSource: '=',
gridheader: '='
},
link: function (scope, element, attrs) {
var grid = new wijmo.grid.FlexGrid(element[0]);
scope.$watch('itemsSource', function () {
grid.itemsSource = scope.itemsSource;
grid.columns[1].width = 300;
grid.selectionMode= "Row";
grid.isReadOnly=true;
});
}
}
The grid's "selection" property returns a CellRange object that contains the selection. It's a get/set property, so you can use it at any time to find out what rows and columns are selected, or to modify the selection.
If a single cell is selected, the range's "row" and "col" properties will contain the indices of the selected row and column. If a range is selected, you can use the ranges "topRow", "leftCol", "bottomRow", and "rightCol" to get the range.
This link describes other useful methods and properties of the CellRange object:
https://wijmo.com/5/docs/topic/wijmo.grid.CellRange.Class.html
I've developed web applications with Dojo for more than one year, and I've used dojox grid a lot, but there is no way to add customize buttons on DataGrid or EnhancedGrid, as I know that ExtJS, or EasyUI, jQuery jqgrid are capable doing this.
So I want to ask if there is any way that can add buttons or other HTML DOM in the dojox.DataGrid?
at least, you can add dojo.form.Button's to it. simly add an element to the structure-property of your DataGrid like that (sorry, due to no-time i just copy pasted it from an actual project of mine...):
{
name: ' ',
field: 'idx',
type: dojox.grid.cells._Widget,
editable: false,
formatter: function (idx) {
return new dijit.form.Button({
_destroyOnRemove: true,
label: 'Bearbeiten',
onClick: function () {
dojo.byId('clickedItemIdx').value = idx + '';
if (reports.entries[idx].type == 'Rufbereitschaft') {
dojo.byId('addOrEditEntry_OCD_btn').click();
} else {
dojo.byId('addOrEditEntry_ASS_btn').click();
}
}
});
}
},
note that my data contains an idx-field which i commit to the onclick-function in order to know which element was clicked. This is the only way i got this to work.
As you may know, you can add multiple of those structure-elements referring to the same field.