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
Related
I'm trying to validate dynamically generated inputs, but I do not know how to do this.
When I add the div that triggers the directive and inserts the inputs dynamically the div adds the 'has-error' class but does not apply the input style, anyone knows the best way to do this that I'm trying to do?
Here is the markup:
<div ng-if="conditionItem.field.id"
ng-class="{true: 'has-error'}[conditionItem.field.hasError]"
dynamic
input-router
source="conditionItem.field"
ng-click="FieldConditionsCtrl.valueTest(conditionItem.field.hasError)"
ng-required="true"
ng-model="conditionItem.situation[$index]">
</div>
Here is the directive how generate the inputs:
(function() {
'use strict';
angular
.module('applicationInputs', ['rzModule', 'focus-if', 'ui.utils.masks'])
.directive('inputRouter', inputRouter);
/** #ngInject */
function inputRouter($compile){
return {
restrict: 'EA',
scope: {
ngModel: '=',
source: '=',
placeholder: '#',
tabIndex: '='
},
link: function(scope, element, attrs) {
var canvas = angular.element(element[0]);
scope.source.editable = angular.isUndefined(scope.source.editable) ? true : scope.source.editable === true;
//used by setting to override selected field
if (angular.isDefined(attrs.dynamic)) {
scope.$watch('source', function () {
var html = '<' + scope.source.type + 'input></' + scope.source.type + 'input>';
canvas.children().detach();
canvas.append($compile(html)(scope));
});
} else {
var html = '<' + scope.source.type + 'input></' + scope.source.type + 'input>';
canvas.append($compile(html)(scope));
}
}
}
}
})();
Here is my style:
.has-error {
border-color: red
}
Try border: 1px solid red; instead of just setting border-color. Border width is 0 by default, so just setting a color isn't enough
Just a couple nitpicky-subjective style comments also:
element is already a jqLite/jquery element, so no need to call angular.element
the scope.source.editable === true assignment can be shortened to !!scope.source.editable if you really want it to be a boolean.
While clever, this sort of jquery style element building is generally a code smell in angular js. If you really want to go this route, I would build self-contained directives for your inputs and use inputRouter's template to choose. It's easier to understand, so your future self will thank you
{true: 'has-error'}[conditionItem.field.hasError] took me a minute. Just write it as {conditionItem.field.hasError: 'has-error'}
I'm a big fan of these style guides for AngularJS:
John Papa - ES5, but good advice
Todd Motto - ES6+
There's overlap, but take what you like from each.
app.directive('hidefileId',['$document','documentService',function($document,documentService){
return{
scope: false,
restrict: 'AE',
link : function($scope,element,attrs){
element.on('click',function(e){
angular.element('#fileId').removeClass("errorhilight");
angular.element('#docerrormsg').html('');
})
}
}
}]);
I have many directives in my js controller, when I use the following directive I am getting the parent scope in
$scope.$parent.$parent.$parent.$parent.// here I am getting the scope of my controller.
even I use scope: false, it is creating new scope.
I want to use the my controller scope only
You can use the require directive option. This will give you access to a parent controller(s). The directive with throw an exception if the controller(s) can not be found. You will have access to anything you put on that controller. This is a great method to use if you need a parent child relationship where a child directive needs access to the parent. It also allows for more modular code.
e.g.
I have written a table directive with an exposed API to add formatting to cells. This is very useful as you can write many additional table directives that can be used interchangeably throughout an application. As an example I will show you a child HoverTitle directive that uses the parent table directive to add a hover tooltip in a given cell.
function HoverTitle(CellProcessService){
'ngInject';
return{
require: '^cTable', // require c-table
link: function(scope, element, attrs, cTable){
cTable.addCellRenderProcess(renderCell, CellProcessService.priorities["HOVER-TITLE"]);
function renderCell(curr, column, row){
if(angular.isFunction(cTable.hoverClass)){
var hoverTitle = cTable.hoverClass(row, curr, column);
if(hoverTitle){
var placement = cTable.placement || 'right';
var tag = column.link ? "span" : 'a'
return '<' + tag + ' tooltip-placement="'+placement+'" uib-tooltip="' + hoverTitle + '">' + curr +'</ ' + tag + '>';
}
}
return curr;
}
}
}
}
Here is how it could be used:
<c-table
table-sort
hover-title
data="$ctrl.data"
columns="$ctrl.columns">
</c-table>
https://docs.angularjs.org/guide/directive#creating-directives-that-communicate
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 :)
First what I want:
I have a series of thumbnails. When I click on one, I want that specific thumbnail to be shown in a bigger div, with its description. (For later: should be animated).
Now I have the directive and the controller, but I don't know how to set the appropriate variable!
So some code:
First HTML: here is the root .jade file for this section. I have a directive called product.
section
.detail-view(ng-show="vm.showDetail")
.prod-desc(ng-bind="vm.detailPic")
.prod-img(ng-bind="vm.detailDesc")
product.col-xs-12.product_tile(ng-repeat="item in vm.products", item="::item")
As you can see, the product directive is part of an ng-repeat; for this reason, the div I want to show the resized image is outside the iteration (.detail-view).
The product directive:
'use strict';
ProductDirective.$inject = ['ShopCart', '$animate', 'User'];
function ProductDirective(ShopCart, $animate, User) {
return {
restrict: 'E',
scope: {
item: '='
},
template: require('./product.html'),
link: link
};
function link(scope, element) {
scope.toggleDetails = toggleDetails;
}
function toggleDetails() {
if (!scope.isSelected && isBlurred()) return;
scope.vm.detailPic = scope.item.photo;
scope.vm.detailDesc = scope.item.prod_description;
scope.vm.isSelected = !scope.isSelected;
scope.showDetail = !scope.showDetail;
var action = scope.isSelected ?
}
}
Now the div I want to update with the image in big is outside the iteration - and hence outside the scope of the directive. How can I set the value of showDetail, showDesc and showPic?
As I am using controllerAs with value vm, I thought I could just do scope.vm.detailPic = scope.item.photo;, as in other solutions I have seen that when setting a property on a root object, it would be propagated...but I get
Cannot set property 'detailPic' of undefined
For now, what works (but looks a bit odd to me) is this, in toggleDetails()
scope.$parent.$parent.vm.detailPic = scope.item.photo;
scope.$parent.$parent.vm.detailDesc = scope.item.prod_description;
scope.$parent.$parent.vm.showDetail = !scope.$parent.$parent.vm.showDetail
I have a directive that displays some data but I want to user of the directive to be able to control how that data is displayed. I would like to allow a user to be able control the display using one of three options.
pass in a string to use for the display
pass in a function that will be called to generate the string
or just show the raw data
I can't post the code for the entire directive (NDA and all) but it is a directive for showing a ring chart using D3. The number in the middle is the piece of data in question. So assuming the ring chart is showing a percentage, I may want the text in the center to say 55%. So assuming myValue is a property on the scope and is set to 55, here is what I would like to do:
<div ring-chart total="100"
remaining="{{myValue}}"
center-number-class="center-number-sm"
remaining-color="#0F79C0"
used-color="#C1D3E6"
chart-width="45"
chart-height="45"
ring-thickness="3"
label-text="{{myValue}}%"></div>
which would show 55%
or do:
<div ring-chart total="100"
remaining="{{myValue}}"
center-number-class="center-number-sm"
remaining-color="#0F79C0"
used-color="#C1D3E6"
chart-width="45"
chart-height="45"
ring-thickness="3"
label-function="ringLabelFunction(remaining)"></div>
which would show whatever ringLabelFunction(value) returns
and finally have the option to do:
<div ring-chart total="100"
remaining="{{myValue}}"
center-number-class="center-number-sm"
remaining-color="#0F79C0"
used-color="#C1D3E6"
chart-width="45"
chart-height="45"
ring-thickness="3"></div>
which would just show 55.
In the directive I have
...
scope: {
total:"#",
remaining:"#",
valueSuffix: "#",
centerNumberClass: "#",
suffixClass: "#",
remainingColor: "#",
totalColor: "#",
chartWidth: "#",
chartHeight: "#",
ringThickness: "#",
labelFunction: "&",
labelText:"#"
},
link:function($scope, element, attrs) {
var labelContent;
if ($scope.labelText) {
labelContent = $scope.labelText;
} else if ($scope.labelFunction) { //<-- this is always true
labelContent = $scope.labelFunction({remaining:$scope.remaining});
} else { //so I never get to this
labelContent = $scope.remaining;
}
...
}
...
So, in short I am looking for a way to determine if $scope.labelFunction has actually been set.
You have link attrs. Just check if label-function is defined and its value refers to function
link:function($scope, element, attrs) {
if(attrs.labelFunction != undefined && typeof(attrs.onStuff) == 'function'){
scope.$eval(attrs.labelFunction);
}
}
Check to see if it's a function:
} else if ($scope.labelFunction && typeof($scope.labelFunction) == "function") {