I am working on list of languages and levels of proficiency. This would be a array of objects:
languages : [
{ name : 'English', level : 'native' },
{ name : 'Spanish', level : 'good' }
]
So I have such definitions of fields:
{
className : 'col-xs-4',
type : 'ui-select',
key : 'languages[' + index + '].name',
templateOptions : {
label : 'Some label',
options : [ ... data there ... ],
required : true
}
},
{
className : 'col-xs-8 btn-radio-language',
type : 'btn-radio',
key : 'languages[' + index + '].level',
templateOptions : {
label : 'Proficiency',
options : ... data for native, good, so so ...
}
}
Those definition would repeat several times with respect of index.
However instead of array languages being addressed with values series of properties in model like:
"languages[0].level": "native",
"languages[1].level": "advanced",
"languages[0].name": "German"
have been created...
How I can point to languages array in model ?
If I've understood it correctly you could map your data with languages.map(function(language) {...}).
Please have a look at the demo below or at this jsfiddle.
angular.module('demoApp', ['formly', 'formlyBootstrap'])
.controller('MainController', function() {
var vm = this;
vm.model = {};
var languages = [
{ name : 'English', level : 'native' },
{ name : 'Spanish', level : 'good' }
];
var createOptionTmpl = function(value) {
return {
name: value,
value: value
};
};
/*
console.log(languages.map(function(lang) {
return {
name: lang.level,
value: lang.level
};
}));*/
vm.fields = [{
className: 'col-xs-4',
type: 'select',
key: 'languages.name',
templateOptions: {
label: 'Some label',
options: languages.map(function(lang) {
return createOptionTmpl(lang.name);
}), //[...data there...],
required: true
}
}, {
className: 'col-xs-8 btn-radio-language',
type: 'radio',
key: 'languages.level',
templateOptions: {
label: 'Proficiency',
options: languages.map(function(lang) {
return createOptionTmpl(lang.level);
})
}
}];
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/api-check/7.5.5/api-check.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-formly/7.3.9/formly.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-formly-templates-bootstrap/6.2.0/angular-formly-templates-bootstrap.min.js"></script>
<div ng-app="demoApp" ng-controller="MainController as vm">
<form ng-submit="vm.onSubmit()">
<formly-form model="vm.model" fields="vm.fields"></formly-form>
<button class="btn btn-primary">
submit
</button>
</form>
{{vm.model}}
</div>
Related
I have been looking for an example for 'multicheckbox' type in 'angular formly form', where the check-boxes are selected or unselected based on corresponding value in form model, when the form is loaded,but could not find any.Can some one please help me with an example?
I shall explain my exact case :
Following is my formly form.Its a multicheckbox with key as 'selectedAnswer'.Initial value for 'selectedAnswer' in the forms model is "ee,dd".But the correspondig values are not getting checked in the check box on loading the form.
[
{
"key":"selectedAnswer",
"type":"multiCheckbox",
"templateOptions":{
"label":"fsdfsdf",
"options":[
{
"name":"ee",
"value":"ee"
},
{
"name":"dd",
"value":"dd"
},
{
"name":"tg",
"value":"tg"
}
]
}
}
]
Please help me to fix this issue.
Thanks,
Deepthy.
click this DEMO for example
HTLM/VIEW
<form novalidate>
<formly-form model="vm.model" fields="vm.Fields" form="vm.rentalForm">
</formly-form>
</form>
Script Code
var vm = this;
vm.model = {
check1: true,
check2:false,
check3:false
};
vm.Fields = [
{
key: 'check1',
type: 'checkbox',
templateOptions: { label: '' },
expressionProperties: {
'templateOptions.label': function(viewValue, modelValue, scope) {
return "check1"
}
}
},{
key: 'check2',
type: 'checkbox',
templateOptions: { label: '' },
expressionProperties: {
'templateOptions.label': function(viewValue, modelValue, scope) {
return "check2"
}
}
},{
key: 'check3',
type: 'checkbox',
templateOptions: { label: '' },
expressionProperties: {
'templateOptions.label': function(viewValue, modelValue, scope) {
return "check3"
}
}
}
];
Hope this works for you.
You can use this type of check box list -
Updated Answer
HTML/View
<form novalidate>
<formly-form model="vm.model" fields="vm.Fields" form="vm.rentalForm">
</formly-form>
</form>
Controller
function MainController(province) {
var vm = this;
vm.model = {
selectedAnswer: ["dd","ee"],
};
vm.Fields =[
{
"key":"selectedAnswer",
"type":"multiCheckbox",
"templateOptions":{
"label":"fsdfsdf",
"options":[
{
"name":"ee",
"value":"ee"
},
{
"name":"dd",
"value":"dd"
},
{
"name":"tg",
"value":"tg"
}
]
}
}
] }
For better understanding check this Fiddle
I have forked the plunk of Santhosh kesavan's answer for providing the better answer.
Hope it will work for you.
For nested keys like below:
{
key: 'domains',
templateOptions: { label: 'Domains' },
fieldGroup: [
{
key: 'domainsCheckbox',
type: 'multicheckbox',
templateOptions: {
options: [
{
key: 'Option1',
value: 'Option1'
},
{
key: 'Option2',
value: 'Option2'
},
]
},
}
]
}
You can specify the model as:
model = {'domains': {'domainsCheckbox': { 'Option1': true }}};
I didn't work for me, in latest version the type has been updated. like type: multiCheckbox --> multicheckbox and options.name --> options.key
[
{
"key":"selectedAnswer",
"type":"multicheckbox",
"templateOptions":{
"label":"fsdfsdf",
"options":[
{
"key":"ee",
"value":"ee"
},
{
"key":"dd",
"value":"dd"
},
{
"key":"tg",
"value":"tg"
}
]
}
}
]
Below code will give you the idea
index.html
<!doctype html>
<html lang="en" ng-app="checkBx">
<head>
<meta charset="UTF-8">
<title>Example - example-ng-selected-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="myCtrl">
<label>Check me to select: <input type="checkbox" ng-model="isSelected"></label><br/>
<label>Check me to select: <input type="checkbox" ng-model="isSecSelected"></label><br/>
</body>
</html>
script.js
var app = angular.module('checkBx', [])
app.controller('myCtrl', ['$scope', myCtrl]);
function myCtrl($scope){
$scope.isSelected = true;
$scope.isSecSelected = false;
}
I would like to show the forms in a modal using the Angle Material, but simply the controller is ignored.
Outside the modal, it operates normally, only the modal giving this problem ..
What did I doing wrong?
Any idea doque do?
angular.module('adminApp.forms', ['formly', 'formlyBootstrap', 'adminApp.services'], function config(formlyConfigProvider) {
formlyConfigProvider.setType({
name : 'repeatSection',
templateUrl : 'repeatSection.html',
controller : function($scope) {
$scope.formOptions = {formState: $scope.formState};
$scope.addNew = addNew;
$scope.copyFields = copyFields;
function copyFields(fields) {
return angular.copy(fields);
}
function addNew() {
$scope.model[$scope.options.key] = $scope.model[$scope.options.key] || [];
var repeatsection = $scope.model[$scope.options.key];
var lastSection = repeatsection[repeatsection.length - 1];
var newsection = {};
// if (lastSection) {
// newsection = angular.copy(lastSection);
// }
repeatsection.push(newsection);
}
}
});
})
.controller('FormsController', function($scope, $mdDialog){
$scope.addField = function(ev){
$mdDialog.show({
parent : angular.element(document.body),
controller : FormsBuilder,
ariaLabel : 'Adicionar Campo',
targetEvent : ev,
clickOutsideToClose : true,
templateUrl : 'partials/tpl/fields.html',
})
function FormsBuilder($scope, FIELDS) {
console.log('start!')
var vm = this;
// funcation assignment
vm.onSubmit = onSubmit;
init();
//vm.originalFields = angular.copy(vm.fields);
// function definition
function onSubmit() {
console.log('submit!');
return
$scope.field = new FIELDS(vm.model);
$scope.field.$save(function(){
$scope.showToast('Field Group ....Criado!');
});
}
function init() {
console.log('init!')
vm.model = {
fields: []
};
vm.fields = [
{
"key": "fieldGroup-name",
"type": "input",
"templateOptions": {
"placeholder": "Nome do Grupo",
"label": "One add-on on the left (icon)"
}
},
{
type: 'repeatSection',
key: 'fields',
templateOptions: {
btnText:'Adicionar novo campo',
fields: [
{
className: 'row',
fieldGroup: [
{
className: 'col-xs-4',
type: 'input',
key: 'fieldName',
templateOptions: {
label: 'Nome do campo:'
}
},
{
type: 'input',
key: 'fieldSlug',
className: 'col-xs-4',
templateOptions: {
label: 'Slug do campo:'
}
}
]
},
{
"type": "select",
"key": "Fieldtype",
"templateOptions": {
"label": "Field Type",
"required": true,
"options": [
{
"name": "Text Field",
"value": "input"
},
{
"name": "TextArea Field",
"value": "textarea"
},
{
"name": "Radio Buttons",
"value": "radio"
},
{
"name": "Checkbox",
"value": "checkbox"
}
]
}
},
{
type: 'checkbox',
model: 'formState',
key: 'selfExecuting',
templateOptions: {
label: 'Are you executing this trade?'
}
},
{
hideExpression: '!formState.selfExecuting',
fieldGroup: [
{
type: 'input',
key: 'relationshipName',
templateOptions: {
label: 'Name:'
}
},
{
type: 'select',
key: 'complianceApprover',
templateOptions: {
label: 'Compliance Approver:',
options: [
{
name: 'approver 1',
value:'some one 1'
},
{
name: 'approver 2',
value:'some one 2'
}
]
}
},
{
type: 'textarea',
key: 'requestorComment',
templateOptions: {
label: 'Requestor Comment',
rows: 4
}
}
]
}
]
}
}
];
}
}
};
});
Modal template:
<md-dialog aria-label="Adicionar Campo">
<md-dialog-content>
<h1>Nome do Grupo: {{vm.exampleTitle}}</h1>
<form ng-submit="vm.onSubmit()" novalidate>
<formly-form model="vm.model" fields="vm.fields" form="vm.form">
<md-button type="submit" class="md-raised md-primary">Salvar</md-button>
</formly-form>
</form>
</md-dialog-content>
</md-dialog>
<script type="text/ng-template" id="repeatSection.html">
<div>
<div class="{{hideRepeat}}">
<div class="repeatsection" ng-repeat="element in model[options.key]" ng-init="fields = copyFields(to.fields)">
<formly-form fields="fields" model="element" bind-name="'formly_ng_repeat' + index + $parent.$index">
</formly-form>
<div style="margin-bottom:20px;">
<md-button type="submit" class="md-raised md-primary" ng-click="model[options.key].splice($index, 1)">Remover campo</md-button>
</div>
<hr>
</div>
<md-button type="button" class="md-raised md-primary" ng-click="addNew()" >{{to.btnText}}</md-button>
</div>
</script>
RESOLVED:
$mdDialog.show({
parent : angular.element(document.body),
controller : FormsBuilder,
controllerAs : 'vm',
ariaLabel : 'Adicionar Campo',
targetEvent : ev,
clickOutsideToClose : true,
templateUrl : 'partials/tpl/fields.html',
})
We are using a custom editor template with custom fields in Agenda View. We have an edit button which fires the editEvent of scheduler. The problem is that, when we update the event, it doesn't fire the update operation.
As you can see, in "add new event" case, it works fine. Also while editing the "repetitive events with series" case, it fires the update operation as desired.
Only problem, we are having is that, while editing a single event (all day event or non-repetitive events), update operation is not fired.
Does anyone have any solution to this?
Here is the link to demo in telerik's dojo :
The HTML:
<div id="example" ng-app="KendoDemos">
<div ng-controller="MyCtrl">
<div class="thisTab clickhereTabScheduledcont boxWrapper">
<div class="agenda" style="position:relative;">
<div kendo-toolbar k-options="toolbarOptions" class="newEvent" id="toolbar" ng-click="schedulerOptions.addEvent()"></div>
<div kendo-scheduler="scheduler" k-options="schedulerOptions">
<span k-event-template class='custom-event'>
<span>{{dataItem.title}}</span>
<hr>
<i class="fa fa-pencil" ng-click="schedulerOptions.editEvent(dataItem)">Edit</i>
</span>
<div k-all-day-event-template class='custom-all-day-event'>{{dataItem.title}}</div>
</div>
</div>
</div>
</div>
Script section:
<script>
angular.module("KendoDemos", [ "kendo.directives" ])
.controller("MyCtrl", function($scope){
$scope.toolbarOptions = {
items: [
{ type: "button", text: "New Event" }
]
};
$scope.schedulerOptions = {
date: new Date("2013/6/13"),
startTime: new Date("2013/6/13 07:00 AM"),
height: 600,
views: [
"agenda"
],
timezone: "Etc/UTC",
editable: {
template: kendo.template($("#customEditorTemplate").html())
},
dataSource: {
batch: true,
transport: {
read: {
url: "http://demos.telerik.com/kendo-ui/service/tasks",
dataType: "jsonp"
},
update: {
url: function (data) {
alert(JSON.stringify(data));
return "http://demos.telerik.com/kendo-ui/service/tasks/update";
},
dataType: "jsonp"
},
create: {
url: function (data) {
alert(JSON.stringify(data));
return "http://demos.telerik.com/kendo-ui/service/tasks/create";
},
},
destroy: {
url: "http://demos.telerik.com/kendo-ui/service/tasks/destroy",
dataType: "jsonp"
},
parameterMap: function(options, operation) {
alert(operation);
}
},
schema: {
model: {
id: "taskId",
fields: {
taskId: { from: "TaskID", type: "number" },
title: { from: "Title", defaultValue: "No title", validation: { required: true } },
start: { type: "date", from: "Start" },
end: { type: "date", from: "End" },
startTimezone: { from: "StartTimezone" },
endTimezone: { from: "EndTimezone" },
description: { from: "Description" },
recurrenceId: { from: "RecurrenceID" },
recurrenceRule: { from: "RecurrenceRule" },
recurrenceException: { from: "RecurrenceException" },
ownerId: { from: "OwnerID", defaultValue: 1 },
isAllDay: { type: "boolean", from: "IsAllDay" }
}
}
},
filter: {
logic: "or",
filters: [
{ field: "ownerId", operator: "eq", value: 1 },
{ field: "ownerId", operator: "eq", value: 2 }
]
}
},
editEvent: function (dataItem) {
alert(JSON.stringify(dataItem));
$scope.scheduler.editEvent(dataItem);
},
addEvent: function () {
$scope.scheduler.addEvent({title: ""});
}
};
})
</script>
Ok,I think first we will pass scheduler event function in edit function.Then you can call api by eventId or as u like.
I have done this issue like that
This is your html template
<div class="thisTab clickhereTabScheduledcont boxWrapper">
<div class="agenda" style="position:relative;">
<div kendo-toolbar k-options="toolbarOptions" class="newEvent" id="toolbar" ng-click="schedulerOptions.addEvent()"></div>
<div kendo-scheduler="scheduler" k-options="schedulerOptions">
<span k-event-template class='custom-event'>
<span>{{dataItem.title}}</span>
<hr>
<i class="fa fa-pencil" ng-click="schedulerOptions.editEvent($event,$event.isRecurrenceHead())">Edit</i>
</span>
<div k-all-day-event-template class='custom-all-day-event'>{{dataItem.title}}</div>
</div>
</div>
</div>
Here is your controller
//you can pass scheduler default function in edit function
var editEventDetails ={};
update: {
url: function (data) {
console.log('update function');
var dt;
data.SignUpDueDate = moment(data.SignUpDueDate).format('YYYY-MM-DD') + "T23:59:59" + ".000Z";
data.ProgramTemplateId = editEventDetails.ProgramTemplateId;
data.IsTeamEvent = editEventDetails.IsTeamEvent;
data.SeasonTeamId = editEventDetails.SeasonTeamId;
data.Description = editEventDetails.Description;
data.CheckAttendance = editEventDetails.CheckAttendance;
data.Remarks = editEventDetails.Remarks;
data.IsSignUpRequired = editEventDetails.IsSignUpRequired;
API.post('/Scheduler/SaveProgramEvent', data).then(function (result) {
}
},
},
editEvent: function (evt) {
var uid = $(evt.target).closest('.k-task').attr("data-uid");
var event = $scope.scheduler.occurrenceByUid(uid);
event.startDate = moment(event.start).format('MM/DD/YYYY h:mm a');
event.endDate = moment(event.end).format('MM/DD/YYYY h:mm a');
dataItem.startDate = moment(event.start).format('MM/DD/YYYY h:mm a');
dataItem.endDate = moment(event.end).format('MM/DD/YYYY h:mm a');
$scope.scheduler.editEvent(event);
},
edit: function (e) {
console.log('EDIT');
if (e.event.eventMetaId != null && e.event.eventMetaId != undefined && e.event.eventMetaId != 0) {
var detailParams = {
EventMetaId: (e.event.recurrenceId !== 0 && e.event.eventMetaId === 0) ? e.event.recurrenceId : e.event.eventMetaId,
OwnerOrganizationId: _orgId,
UserTimezone: global.userTimezoneOffset// userTimezone
};
API.get('/Scheduler/GetEventDetailById', detailParams).then(function (data) {
editEventDetails = data;
mapEventDetail(editEventDetails, e.event)
});
setTimeout(function () {
e.event.startDate = moment(e.event.start).format('MM/DD/YYYY h:mm a');
e.event.endDate = moment(e.event.end).format('MM/DD/YYYY h:mm a');
e.event.recurrenceException = editEventDetails.recurrenceException;
$scope.$apply();
}, 0);
}
},
Here mapEventDetail is map function database and scheduler model
you can use mapEventDetail like that:--
var mapEventDetail = function (fromObj, toObj) {
toObj.programTemplateId = fromObj.ProgramTemplateId;
toObj.isTeamEvent = fromObj.IsTeamEvent;
toObj.seasonTeamId = fromObj.SeasonTeamId;
toObj.description = fromObj.Description;
toObj.checkAttendance = fromObj.CheckAttendance;
toObj.remarks = fromObj.Remarks;
return toObj;
};
I need to create bar chart showing up various values, such as "Created", "Closed", "Submitted" data with count on Y Axis and dates on x axis.
I am able to do this successfully, for any one criteria. However I am not able to get multiple bars being shown.
Below is the code I am using currently:
<!DOCTYPE html>
<html>
<head>
<title>Defect Trend App</title>
<script type="text/javascript" src="/apps/2.0rc1/sdk.js"></script>
<script type="text/javascript">
Rally.onReady(function () {
(function() {
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
return this.createTrendChart();
},
createTrendChart: function() {
var ProjectOid;
ProjectOid = this.getContext().getProject().ObjectID;
var ReleaseOID = <My Release ID>;
Ext.define('My.TrendCalc', {
extend: 'Rally.data.lookback.calculator.TimeSeriesCalculator',
getMetrics: function() {
return [
{
as: 'Defects',
display: 'column',
f: 'count'
}
];
}
});
this.myTrendChart = Ext.create('Rally.ui.chart.Chart', {
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: {
find: {
_TypeHierarchy: "Defect",
State: {
$lt: "Closed"
},
_ProjectHierarchy: ProjectOid,
Release: ReleaseOID
},
fetch: ["_ValidFrom", "_ValidTo", "ObjectID"]
},
calculatorType: 'My.TrendCalc',
calculatorConfig: {},
chartConfig: {
chart: {
zoomType: 'x',
type: 'column'
},
title: {
text: 'Defects over Time'
},
xAxis: {
type: 'datetime',
minTickInterval: 1
},
yAxis: {
title: {
text: 'Number of Defects'
}
}
}
});
return this.add(this.myTrendChart);
}
});
}).call(this);
Rally.launchApp('CustomApp', {
name:"Defect Trend App",
parentRepos:""
});
});
</script>
<style type="text/css">
.app {
/* Add app styles here */
}
</style>
</head>
<body></body>
</html>
I do not consider myself an expert in this area, but I believe this will work for you...
I took your code as a base and modified it based on some other code to get what I think appears to be a working version of what you want. Below is a screenshot of the code running in Rally.
The data I had did not have a lot of variance in the series (most were released) so it looks uninteresting.
You will probably want to exclude the final state (as I believe you did in your code via the $lt:'Completed'... which i changed to $lte:'Completed' temporarily).
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html><head><title>
Defect Trend App </title>
<script type="text/javascript" src="/apps/2.0rc1/sdk.js"></script>
<script type="text/javascript">
var states = ['Accepted','Released']; // all enum values for 'State'
var field = 'ScheduleState'; // or 'State'
var ReleaseOID = XXXXXX; // your release Oid
Rally.onReady(function () {
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
return this.createTrendChart();
},
createTrendChart: function() {
var ProjectOid;
ProjectOid = this.getContext().getProject().ObjectID;
Ext.define('My.TrendCalc', {
extend: 'Rally.data.lookback.calculator.TimeSeriesCalculator',
getDerivedFieldsOnInput: function() {
var m = _.map(states, function(state) {
return {
"as": state,
"f" : function(snapshot) {
var value = (snapshot[field] == state) ? 1 : 0;
return value;
}
}
})
return m;
},
getMetrics : function() {
var m = _.map(states, function(state) {
return {
field: state,
as: state,
f: 'sum'
}
})
return m;
}
});
this.myTrendChart = Ext.create('Rally.ui.chart.Chart', {
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: {
find: {
_TypeHierarchy: "Defect",
State: {$lte: "Closed" },
_ProjectHierarchy: ProjectOid,
Release: ReleaseOID
},
fetch: ["_ValidFrom", "_ValidTo", "ObjectID", field],
hydrate: [field],
sort: { "_ValidFrom" : 1}
},
calculatorType: 'My.TrendCalc',
calculatorConfig : {},
chartConfig: {
chart: {
zoomType: 'xy',
type:'column'
},
title: {
text: 'Defects over Time'
},
xAxis: {
type: 'datetime',
title: { text: 'When'},
minTickInterval: 5,
labels : { rotation: 90 }
},
yAxis: { title: { text: 'Count' } },
plotOptions: {
series: {
stacking: 'normal'
}
}
}
});
return this.add(this.myTrendChart);
}
});
});
console.log("launching application");
Rally.launchApp('CustomApp', {
name:'Defect Trend App',
parentRepos:""
});
</script>
</head>
<body>
</body>
Pastebin - http://pastebin.com/Vf6jniGZ
I'm not familiar with Rally's App SDK wrappers, but I'm the primary author of Lumenize where the TimeSeriesCalculator comes from. Your situation is exactly what the group-by functionality in Lumenize.TimeSeriesCalculator was designed for. See the documentation for a careful walkthrough of how the TimeSeriesCalculator works. Look at the second example titled, "Time-series group-by example". Also, here is a functioning jsfiddle of that group-by example.
The key bit that you need is:
metrics = [
...
{f: 'groupByCount', groupByField: 'ScheduleState', allowedValues: allowedValues, prefix: 'Count '},
...
]
I'm experimenting with AngularJS. I want to show a basic Kendo Grid. I'm trying to do this using pure directives. With that in mind, I've looked at the Kendo UI / Angular JS project (https://github.com/kendo-labs/angular-kendo). Unfortunately, my
index.html:
<div>Products: {{products.length}}</div>
<div kendo-grid k-data-source="products" k-selectable="'row'"
k-pageable='{ "refresh": true, "pageSizes": true }'
k-columns='[
{ "field": "Name", "title": "Name"},
{ "field": "Department", "title": "Department"},
{ "field": "LastShipment", "title": "Last Shipment" }
]'>
</div>
controllers.js
function myController($scope) {
console.log("initializing controller...");
$scope.products = [
{ id:1, name:'Tennis Balls', department:'Sports', lastShipment:'10/01/2013' },
{ id:2, name:'Basket Balls', department:'Sports', lastShipment:'10/02/2013' },
{ id:3, name:'Oil', department:'Auto', lastShipment:'10/01/2013' },
{ id:4, name:'Filters', department:'Auto', lastShipment:'10/01/2013' },
{ id:5, name:'Dresser', department:'Home Furnishings', lastShipment:'10/01/2013' }
];
}
I've verified that I've wired up the controller properly. The activity count shows properly. However, the grid does not appear. I can't figure out what I'm doing incorrectly.
Thank you for your help.
You can also setup a Kendo DataSource as an AngularJS Service using the Factory method and inject this into your Controller to conform to AngularJS best practices and patterns.
Full source code and live demo: http://goo.gl/6Z9jop
Customer.cshtml
#{
ViewBag.Title = "Index";
}
<div>
<h2 ng-cloak>{{title}}</h2>
<div>
<div class="demo-section">
<div class="k-content" style="width: 100%">
<div kendo-grid="grid"
k-sortable="true"
k-pageable="true"
k-filterable="true"
k-editable="'inline'"
k-selectable="true"
k-columns='[
{ field: "CustomerID", title: "ID", width: "75px" },
{ field: "CompanyName", title: "Company"},
{ field: "ContactName", title: "Contact" },
{ field: "ContactTitle", title: "Title" },
{ field: "Address" },
{ field: "City" },
{ field: "PostalCode" },
{ field: "Country" },
{ field: "Phone" },
{ field: "Fax" }]'
>
</div>
<style scoped>
.toolbar { padding: 15px; float: right; }
</style>
</div>
</div>
<script type="text/x-kendo-template" id="toolbar">
<div>
<div class="toolbar">
<button kendo-button ng-click="edit(this)"><span class="k-icon k-i-tick"></span>Edit</button>
<button kendo-button ng-click="destroy(this)"><span class="k-icon k-i-tick"></span>Delete</button>
<button kendo-button ng-click="details(this)"><span class="k-icon k-i-tick"></span>Edit Details</button>
</div>
<div class="toolbar" style="display:none">
<button kendo-button ng-click="save(this)"><span class="k-icon k-i-tick"></span>Save</button>
<button kendo-button ng-click="cancel(this)"><span class="k-icon k-i-tick"></span>Cancel</button>
</div>
</div>
</script>
</div>
</div>
customerController.js
'use strict';
northwindApp.controller('customerController',
function ($scope, $rootScope, $location, customerDataSource)
{
customerDataSource.filter({}); // reset filter on dataSource everytime view is loaded
var onClick = function (event, delegate)
{
var grid = event.grid;
var selectedRow = grid.select();
var dataItem = grid.dataItem(selectedRow);
if (selectedRow.length > 0)
{
delegate(grid, selectedRow, dataItem);
}
else
{
alert("Please select a row.");
}
};
$scope.toolbarTemplate = kendo.template($("#toolbar").html());
$scope.save = function (e)
{
onClick(e, function (grid)
{
grid.saveRow();
$(".toolbar").toggle();
});
};
$scope.cancel = function (e)
{
onClick(e, function (grid)
{
grid.cancelRow();
$(".toolbar").toggle();
});
},
$scope.details = function (e)
{
onClick(e, function (grid, row, dataItem)
{
$location.url('/customer/edit/' + dataItem.CustomerID);
});
},
$scope.edit = function (e)
{
onClick(e, function (grid, row)
{
grid.editRow(row);
$(".toolbar").toggle();
});
},
$scope.destroy = function (e)
{
onClick(e, function (grid, row, dataItem)
{
grid.dataSource.remove(dataItem);
grid.dataSource.sync();
});
},
$scope.onChange = function (e)
{
var grid = e.sender;
$rootScope.lastSelectedDataItem = grid.dataItem(grid.select());
},
$scope.dataSource = customerDataSource;
$scope.onDataBound = function (e)
{
// check if there was a row that was selected
if ($rootScope.lastSelectedDataItem == null)
{
return;
}
var view = this.dataSource.view(); // get all the rows
for (var i = 0; i < view.length; i++)
{
// iterate through rows
if (view[i].CustomerID == $rootScope.lastSelectedDataItem.CustomerID)
{
// find row with the lastSelectedProductd
var grid = e.sender; // get the grid
grid.select(grid.table.find("tr[data-uid='" + view[i].uid + "']")); // set the selected row
break;
}
}
};
});
customerDataSource.js
'use strict';
northwindApp.factory('customerDataSource',
function (customerModel)
{
var crudServiceBaseUrl = "/odata/Customer";
return new kendo.data.DataSource({
type: "odata",
transport: {
read: {
async: false,
url: crudServiceBaseUrl,
dataType: "json"
},
update: {
url: function (data)
{
return crudServiceBaseUrl + "(" + data.CustomerID + ")";
},
type: "put",
dataType: "json"
},
destroy: {
url: function (data)
{
return crudServiceBaseUrl + "(" + data.CustomerID + ")";
},
dataType: "json"
}
},
batch: false,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 10,
schema: {
data: function (data) { return data.value; },
total: function (data) { return data["odata.count"]; },
model: customerModel
},
error: function (e)
{
alert(e.xhr.responseText);
}
});
});
It looks as if the field names are spelled wrong. The following works for me:
<div kendo-grid k-data-source="products" k-selectable="'row'"
k-pageable='{ "pageSize": 2, "refresh": true, "pageSizes": true }'
k-columns='[
{ "field": "name", "title": "Name"},
{ "field": "department", "title": "Department"},
{ "field": "lastShipment", "title": "Last Shipment" }
]'>
</div>
Here is a live demo: http://jsbin.com/odeQAfI/2/edit
To avoid the NaN message in the pager you need to make the products field to be a Kendo DataSource:
function MyController($scope) {
$scope.products = new kendo.data.DataSource({
data: [
{ id:1, name:'Tennis Balls', department:'Sports', lastShipment:'10/01/2013' },
{ id:2, name:'Basket Balls', department:'Sports', lastShipment:'10/02/2013' },
{ id:3, name:'Oil', department:'Auto', lastShipment:'10/01/2013' },
{ id:4, name:'Filters', department:'Auto', lastShipment:'10/01/2013' },
{ id:5, name:'Dresser', department:'Home Furnishings', lastShipment:'10/01/2013' }
],
pageSize: 2
});
}
Here is a live demo: http://jsbin.com/ODElUfO/2/edit