I have a dynamically-driven ng-click call inside a cellTemplate call that should fire a function call to open a previously defined Ionic modal, but when I run the click event on entries in the datagrid, the associated scope function call never fires.
I'm not clear if the issue is caused by scope range, or the mechanism of building the function call problematically. Any ideas as to what the cause could be?
//Generator for edit links in the grid cell
$scope.makeEditButtons = function (gridName) {
return "<i class='icon ion-gear-a' ng-click='openEdit" + gridName + "Modal(row.entity)' title='Edit' style='cursor:pointer;'></i> <i class='icon ion-alert' ng-click='openDelete" + gridName + "Modal(row.entity)' title='Delete' style='cursor:pointer;'></i>";
};
//Cell declarations for grid for "Custom Costs"
$scope.custom_costs_columns = [
{field: "description", displayName: "Description", width: '35%'},
{field: 'cost', displayName: "Cost", width: '35%', cellClass: 'text-right', cellFilter: 'currency'},
{field: 'edit', displayName: "Actions", cellTemplate: $scope.makeEditButtons("CustomCost"), cellClass: 'text-center'}
];
// UI-Grid initalize
$scope.CustomCostOptions = {
enableSorting: true,
columnDefs: $scope.custom_costs_columns,
enableCellSelection: true,
enableRowSelection: false,
enableCellEdit: false,
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
}
};
//Ionic Modal declare and click function
$scope.deleteCustomCostModal = $ionicModal.fromTemplate({{Template}}, function ($ionicModal) {
$scope.modal = $ionicModal;
},
{
scope: $scope,
focusFirstInput: true
});
$scope.openDeleteCustomCostModal = function (row) {
console.debug(row);
$scope.deleteCustomCostModal.show();
};
One possible issue with not being able to click the created button is because the $scope has not recieved the compiled elemt yet.
Modify the function to
$scope.makeEditButtons = function (gridName) {
return $compile("<i class='icon ion-gear-a' ng-click='openEdit" + gridName + "Modal(row.entity)' title='Edit' style='cursor:pointer;'></i> <i class='icon ion-alert' ng-click='openDelete" + gridName + "Modal(row.entity)' title='Delete' style='cursor:pointer;'></i>")($scope);
};
Use the following function and call it right before the click event.
$scope.applyToview=function(){ if ($scope.$root.$$phase != '$apply' &&
$scope.$root.$$phase != '$digest') {
$scope.$apply();
}
}
Good luck.
First, you need to declare the function to handle click event in appScopeProvider.
Then call it in cellTemplate
Ex:
vm.gridOptions = {
columnDefs: [
{field: 'edit', displayName: "Actions", cellTemplate: '<span ng-click="grid.appScope.clickHandler(row)">Edit</span>'}
],
................
appScopeProvider: {
clickHandler: onCellClick
}
}
function onCellClick(row){
console.log(row.entity);
}
Hope it helps!
First, your cellTemplate should be just that. It should look something like this:
cellTemplate: '<i class="icon ion-gear-a" style="text-decoration:underline; color: blue; cursor:pointer;" ng-click="grid.appScope.openDeleteCustomCostModal(row)">{{COL_FIELD}}</i><i class='icon ion-alert' ng-click="grid.appScope.deleteCostModal(row)" title='Delete' style='cursor:pointer;'></i>'
This will call the two functions you have when clicked.
Related
I'm using Angular UI-Grid.
This is the grid implementation:
JS
var statusCellTemplate =
'<div class="ui-grid-cell-contents"><span ng-
if="row.entity.statusDetails.length>=2" title="My Tooltip">[Multiple Statuses]
</span></span></div>';
vm.propertyListGridOptions = {
appScopeProvider: vm,
flatEntityAccess: false,
fastWatch: true,
showHeader: false,
columnDefs: [
{
name: app.localize('ListingStatus'),
cellTemplate: statusCellTemplate,
width: 240,
},
],
data: []
};
I need to show the ToolTip by using below logic.Can you tell me how to implement such a logic with the above cellTemplate ?
_.each(row.entity.statusDetails, function (s) {
vm.statusValues += s.status.name + ', ';
});
Note : _.each can be a ng-repeat on angular.
I am using a cell template for each row in my data grid. If I qualify the json object with an index then the value appears correctly but of course it is the same for each row. If I remove the index, then all rows are displayed with the same value but the value is an array.
---the js file
(function() {
angular.module('xxxSurvey').controller('EditxxxSurveyController', EditxxxSurveyController);
EditxxxSurveyController.$inject = ['$scope', 'UserFacilityListService', 'xxxSurveyService'];
function EditxxxSurveyController($scope, UserFacilityListService, xxxSurveyService) {
$scope.dataLoaded = false;
$scope.currentPage = 1;
$scope.pageSize = 10;
// test ui-grid setup
$scope.dataLoaded = true;
$scope.editWorksheetOptions = {
enableSorting: true,
columnDefs: [
{
name: 'all', field: 'MasterPatientId', width: 40,
enableSorting: false, enableColumnMenu: false, pinnedLeft: true,
//cellTemplate: '<input type="checkbox" id="i{{COL_FIELD}}">'
cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.worksheetInfo.MasterProviderId}}</div>'
},
{name: 'residentName', field: 'residentName', minWidth: 90, pinnedLeft: true,
cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.editWorksheetOptions.data[0].ResidentNameLast}}</div>'
},
{name: 'residentRoom', field: 'residentRoom', width: 90, pinnedLeft: true},
{name: 'status', field: 'status', width: 90},
],
data: []
};
$scope.$on('FacilitySelected', function() {
if (UserFacilityListService.getSelectedFacility()) {
$scope.selectedFacility = UserFacilityListService.getSelectedFacility();
}
var promise = xxxSurveyService.getCurrentWorksheet($scope.selectedFacility.MasterProviderId);
promise.then(
function(payload) {
if (payload !== null) {
$scope.worksheetInfo = payload.worksheetInfo;
$scope.editWorksheetOptions.data = payload.residentData;
}
}
);
});
}
})();
--the json data
[{"AssessmentId":1,"WorksheetId":4,"MasterPatientId":1,"ResidentNameFirst":"xx","ResidentNameMiddle":"^","ResidentNameLast":"zzz","ResidentNameSuffix":"^"},
{"AssessmentId":2,"WorksheetId":2,"MasterPatientId":2,"ResidentNameFirst":null,"ResidentNameMiddle":null,"ResidentNameLast":null,"ResidentNameSuffix":null}]
--the html div id="editWorksheetGrid" ui-grid="editWorksheetOptions" class="grid" ui-grid-pinning>
i had same issue. For me it was rowIdentity problem.
Define following in your controller.
$scope.gridOptions.rowIdentity = function (row) {
return row.ID; //make sure ID is unique.
};
This fixed my problem.
Thanks
I constructed a ui grid which has a column for editing, the grid information is populated by a json. Upon clicking the edit column a modal is opened. I want the user to be able to edit the row it clicked. So far I was able to return the entire json object to the modal, but I'm having trouble understanding how to turn that object into just the row I want to edit. I have a variable named ClickedRow which returns the $$hashkey id but I'm not sure how to access it. I tried a forEach utility but it's not working. I am new to angularjs can anyone help me
This is my controller:
import {safeApply} from 'ems';
import modalTemplate from './modal/modal.html';
import controller from './modal/modal.controller.js';
class AssetsController {
/* #ngInject */
constructor(AssetsService, $uibModal, $state) {
this.label = 'Assets Controller !!';
this.assetsService = AssetsService;
this.assetModal= $uibModal;
this.$state = $state;
var assetsData;
var clickedRow;
this.assetsService.resolvePromise().then((response) => {
this.gridOptions.data = response;
assetsData = this.gridOptions.data;
//console.log(response);
safeApply();
});
this.modalOptions ={
template: modalTemplate,
controller: controller,
size: 'large',
backdrop: false,
resolve: {
assetData: function(){
console.log('number 2'+clickedRow);
return [clickedRow, assetsData];
}
}
};
this.myAppScopeProvider ={
modal: this.assetModal,
modalOptions: this.modalOptions,
open:function(row){
console.log('number 1'+row);
clickedRow = row;
this.modal.open(this.modalOptions)
}
};
this.initialize();
}
initialize() {
this.gridOptions = {
paginationPageSizes: [15, 30, 45],
paginationPageSize: 9,
rowHeight: 50,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
enableColumnResizing: true,
enableSelectAll: false,
noUnselect: true,
columnDefs: [
{
field: 'Thumbnail',
displayName: '',
width: 100,
cellTemplate: '<span class="glyphicon glyphicon-picture" aria-hidden="true"></span>'
},
{
field: 'File Name',
displayName: 'File Name',
cellClass:'blue',
width: 100
},
{
field: 'Description_',
displayName: 'Description',
minWidth: 150
},
{
field: 'Edit_',
displayName: 'Edit',
cellTemplate: '<button class="btn btn-link pull-right" ng-click="grid.appScope.open(row)">Edit</button>',
cellClass:'blue',
width: 100
},
{ field: 'Uploaded_Date', displayName: 'Upload Date'},
{ field: 'Uploaded_By'},
{ field: 'File_Size' },
{ field: 'File_Source'},
{ field: 'In_Use'},
{
field: 'Lock_Status',
displayName: '',
cellClass:'black',
cellTemplate: '<span class="glyphicon glyphicon-lock" aria-hidden="true">'
}
],
onRegisterApi:function (gridApi) {
this.gridApi = gridApi;
},
appScopeProvider: this.myAppScopeProvider,
rowTemplate:''
};
}
}
export default AssetsController;
class ModalController {
/* #ngInject */
constructor($scope, $uibModalInstance, assetData) {
this.label = 'Modal Controller !!';
this.scope = $scope;
this.scope.assetData = assetData;
}
initialize() {
/* this.modalService.resolvePromise().then((response) => {
this.data = response.data;
});*/
}
}
export default ModalController;
Pass row.entity as parameter to your open method:
<button class="btn btn-link pull-right" ng-click="grid.appScope.open(row.entity)">Edit</button>
You'll need to declare your resolve object in your open method so you can pass entity directly:
open: function (entity) {
this.modalOptions.resolve = {
entity: entity
}
this.modal.open(this.modalOptions)
}
Inject entity into your modal controller and you're good to go
Here's a working example on Plunker: http://plnkr.co/edit/Agvcc6CZFBvQQLRpQeRk?p=preview
I am using angularjs with ui-grid. One column of the grid contains a timestamp that I would like to render as a properly formatted date.
Up to now, I tried like this but the function is never called.
$scope.formatDate = function(date) {
return '42';
};
$scope.columns = [
{field: 'date', cellTemplate: '<div class="ui-grid-cell-contents">formatDate({{row.entity.date}})</div>'},
{field: 'title'},
{field: 'quantity'},
//[...]
];
Instead, the function call is considered as a string literal. As a result, the column always displays formatDate(*timestamp*).
I only found a non-satisfying way of achieving it by defining a function on each single row when receiving them :
$scope.columns = [
{field: 'getFormattedDate()'},
//[...]
];
$http.post('/api/data/').success(function (data) {
$scope.gridOptions.data = data.elements;
$scope.gridOptions.data.forEach(function(row) {
row.getFormattedDate = function() {
return '42';
}
})
});
Any better suggestion?
If you want to access controller scope level functions using ui-grid you can use grid.appScope, here is a quick example:
{
name: 'date',
cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.parseDate(row.entity.date)}}</div>'
}
Full Example:
angular.module('myApp', ['ui.grid'])
.controller('myCtrl', ['$scope', function ($scope) {
$scope.parseDate = function (p) {
// Just return the value you want to output
return p;
}
$scope.parseName = function (p) {
// Just return the value you want to output
return p;
}
$scope.gridOptions = {
data: [{
name: "Foo",
date: "2015-10-12"
}, {
name: "Bar",
date: "2014-10-12"
}],
columnDefs: [{
name: 'name',
cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.parseName(row.entity.name)}}</div>'
}, {
name: 'date',
cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.parseDate(row.entity.date)}}</div>'
}]
};
}]);
Fiddle Example
To use function output the whole function call, not the arguments , needs to be wrapped in expression braces
<div class="ui-grid-cell-contents">{{ formatDate(row.entity.date) }}</div>
It's worth noting that the cellTemplate will not do anything if you don't include HTML in the format:
will not hit the formatting method "formatRating()":
columnDefs: [
{
name: 'starRating', headerCellClass: 'blue', headerTooltip: 'Star Rating',
cellTemplate: '{{grid.appScope.formatRating(row.entity.starRating)}}'
},
Works with the addition of a <span> in the cellTemplate:
columnDefs: [
{
name: 'starRating', headerCellClass: 'blue', headerTooltip: 'Star Rating',
cellTemplate: '<span>{{grid.appScope.formatRating(row.entity.starRating)}}</span>'
},
my format method:
$scope.formatRating = function (starRating) {
switch (starRating) {
case "ONE": return "1/5"; break;
case "TWO": return "2/5"; break;
case "THREE": return "3/5"; break;
case "FOUR": return "4/5"; break;
case "FIVE": return "5/5"; break;
}
}
I use the controllerAs: 'vm' option on my controller, so I had to do the following to call functions in a cellTemplate.
Define the function on the vm scope like this:
vm.$scope.getBitFlag = (flags, value) => (flags & value) ? "✅" : "⬜️";
Then use it like this:
cellTemplate: "<div>{{ grid.appScope.getBitFlag(row.entity.prefValue, 1) }}</div>"
I am trying to read value in array in factory but I am unable to do so. I am using ng-grid and when I click on one row I get selecteditems list which I pass in another controller where I call a factory service in which I pass that as a parameter but that parameter in the factory stays as array and when I read it using index it shows blank.
My code is as below -
myNgApp.controller('MyGrid', ['$scope', function ($scope) {
$scope.mySelections = [];
$scope.mySelItems = [];
$scope.myData = [{ Reference: 12, Customer: "fff", Title: "sd", Task: "Enter Details", Received: "Today", Due: "01/09/2014" },
{ Reference: 7899, Customer: "eee", Title: "dsd", Task: "Enter Details", Received: "Yesterday", Due: "05/09/2014" }];
$scope.gridOptions = {
data: 'myData',
checkboxHeaderTemplate: '<input class="ngSelectionHeader" type="checkbox" ng-model="allSelected" ng-change="toggleSelectAll(allSelected)"/>',
selectWithCheckboxOnly: true,
showSelectionCheckbox: true,
selectedItems: $scope.mySelections,
multiSelect: true,
columnDefs: [{ field: 'Reference', displayName: 'Reference', width: '*' }, { field: 'Customer', displayName: 'Customer', width: '**' }, { field: 'Title', displayName: 'Title', width: '***' }, { field: 'Task', displayName: 'Task', width: '***' }, { field: 'Received', displayName: 'Received', width: '**' }, { field: 'Due', displayName: 'Due', width: '**' }],
showGroupPanel: true,
enableCellSelection: false,
enableRowSelection: true,
enableCellEditOnFocus: false,
enablePinning: true,
showColumnMenu: true,
showFilter: true,
enableColumnResize: true,
enableColumnReordering: true,
maintainColumnRatios: true,
afterSelectionChange: function () {
angular.forEach($scope.mySelections, function (item) {
if ($scope.mySelItems.length == 0) {
$scope.mySelItems.push(item.Title)
}
else {
$scope.mySelItems[0] = item.Title
}
});
}
};
}]);
myNgApp.factory('myPreviewDataService', function () {
return function (x) {
var arr = [x, "Apple", "Banana", "Orange"];
return arr
};
});
myNgApp.factory('myPreviewTplService', function () {
return function () {
return '<div><div class="ngPreviewItems" ng-repeat="item in items">{{item}}</div></div>';
};
});
myNgApp.directive('showPreview', function ($compile) {
return {
scope: true,
link: function (scope, element, attrs) {
var el;
attrs.$observe('template', function (tpl) {
if (angular.isDefined(tpl)) {
// compile the provided template against the current scope
el = $compile(tpl)(scope);
// stupid way of emptying the element
element.html("");
// add the template content
element.append(el);
}
});
}
};
});
myNgApp.controller('myPreviewController', function ($scope, myPreviewDataService, myPreviewTplService) {
//$scope.showContent = function () {
$scope.items = myPreviewDataService($scope.mySelItems);
$scope.template = myPreviewTplService();
//};
});
here $scope.mySelItems is from ng grid controller that gets updated when we select a checkbox.
What I get is an array but I am unable to read its content, when I display the array as it is it gets displayed like ["test"] but when I try to read it x[0] in myPreviewDataService factory or by $scope.mySelItems[0] in myPreviewController then I get blank. I am not able to figure out why this is happening
I was able to solve it. In myPreviewDataService factory I changed the array elements from string to array
var arr = [x, "Apple", "Banana", "Orange"];
changed to
var arr = [x, ["Apple"], ["Banana"], ["Orange"]];
and in myPreviewTplService factory I changed {{item}} to {{item[0]}}
it worked.
P.S I think we can also use ng switch based on condition in myPreviewTplService factory based on the type of item, I tried to do it but I was not able to do so and worked with my earlier solution.