jQuery.Deferred exception: Cannot read property 'models' of undefined - kendo-grid

I'm not sure how to debug this error.
I have a kendo grid that allows users to drag and drop to sort rows and also allows users to update a cell in those rows. However after adding the sort functionality I get this error when trying to update a row:
jQuery.Deferred exception: Cannot read property 'models' of undefined TypeError: Cannot read property 'models' of undefined
I have this code:
#(Html.Kendo().Grid<DocumentProperties>(Model.CurrentList)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.ID).Visible(false);
columns.Bound(p => p.SortOrder).Visible(false);
columns.Bound(p => p.DisplayText).Title("Title");
columns.Bound(p => p.FileName).Title("File Name");
columns.Bound(p => p.ID).ClientTemplate(#Html.ActionLink("View", "ViewDocument", new { id = "did" }, new { target = "_blank" }).ToHtmlString().Replace("did", "#: ID #")).Title("").Width(80); //creates link to view the uploaded document
columns.Bound(p => p.ID).ClientTemplate(#Html.ActionLink("Remove", "DeleteDocument", new { id = "did" }, new { onclick = "return confirm('Are you sure you want to delete this document?');", style = "color:Red;" }).ToHtmlString().Replace("did", "#: ID #")).Title("").Width(80);
columns.Command(commands =>
{
commands.Edit(); // The "edit" command will edit and update data items.
}).Title("").Width(80);
})
.DataSource(dataSource => dataSource
.Ajax()
.Update(update => update.Action("DocAttributeUpdate", "Blurb")) // Action invoked when the user saves an updated data item.
.Events(events => events.Error("error_handler"))
.PageSize(20)
.ServerOperation(false)
.Model(model =>
{
model.Id(p => p.ID); // Specify the property which is the unique identifier of the model.
model.Field(p => p.ID).Editable(false); // Make the ID property not editable.
model.Field(p => p.SortOrder).Editable(false); // Make the SortOrder property not editable.
model.Field(p => p.FileName).Editable(false); // Make the FileName property not editable.
model.Field(p => p.DisplayText).Editable(true); // Make the DisplayText property editable.
})
)
.Sortable(sortable => sortable
.Enabled(true)
)
.Pageable(pageable => pageable
//.Refresh(true) Need to figure this out. Doesn't refresh properly.
.PageSizes(true)
.ButtonCount(5))
.Resizable(r => r.Columns(true))
.Selectable(selectable => selectable.Mode(GridSelectionMode.Single).Type(GridSelectionType.Row)) //make each row selectable
)
#(Html.Kendo().Sortable() //this adds the cool drag and drop sorting
.For("#Grid")
.Filter("table > tbody > tr")
.Cursor("move")
.HintHandler("noHint")
.PlaceholderHandler("placeholder")
.ContainerSelector("#Grid tbody")
.Events(events => events.Change("onChange"))
)
<script type="text/javascript">
var noHint = $.noop;
function placeholder(element) {
return element.clone().addClass("k-state-hover").css("opacity", 0.65);
}
function onChange(e) {
var grid = $("#Grid").data("kendoGrid"),
skip = grid.dataSource.skip(),
oldIndex = e.oldIndex + skip,
newIndex = e.newIndex + skip,
dataItems = grid.dataSource.data(),
dataItem = grid.dataSource.getByUid(e.item.data("uid")); //grab your item and give it a new index. Then remove the item from the list and place in the new index.
grid.dataSource.remove(dataItem);
grid.dataSource.insert(newIndex, dataItem);
var dataList = [];
for (var i = 0; i < dataItems.length; i++) {
dataList[i] = {
ID: dataItems[i].ID,
ClientId: dataItems[i].ClientId,
SortOrder: i,
DisplayText: dataItems[i].DisplayText,
Type: dataItems[i].Type,
MimeType: dataItems[i].MimeType,
FileName: dataItems[i].FileName
};
}
$.ajax({
url: "/Blurb/SaveSortOrder",
type: "POST",
data: {
data: JSON.stringify(dataList) //send our json string back to the server for sorting
}
})
};
When I remove the code for:
#(Html.Kendo().Sortable()
The update button works again, but I don't have my drag and drop sorting anymore.
jQuery Script:
<script>
jQuery(function() {
jQuery("#Grid").kendoGrid({
"columns": [{
"title": "Title",
"headerAttributes": {
"data-field": "DisplayText",
"data-title": "Title"
},
"field": "DisplayText",
"encoded": true,
"editor": "\u003cinput class=\"text-box single-line\" id=\"DisplayText\" name=\"DisplayText\" type=\"text\" value=\"\" /\u003e\u003cspan class=\"field-validation-valid\" data-valmsg-for=\"DisplayText\" data-valmsg-replace=\"true\"\u003e\u003c/span\u003e"
}, {
"title": "File Name",
"headerAttributes": {
"data-field": "FileName",
"data-title": "File Name"
},
"field": "FileName",
"encoded": true
}, {
"headerAttributes": {
"data-field": "ID",
"data-title": ""
},
"width": "80px",
"template": "\u003ca href=\"/Blurb/ViewDocument/#: ID #\" target=\"_blank\"\u003eView\u003c/a\u003e",
"field": "ID",
"encoded": true
}, {
"headerAttributes": {
"data-field": "ID",
"data-title": ""
},
"width": "80px",
"template": "\u003ca href=\"/Blurb/DeleteDocument/#: ID #\" onclick=\"return confirm(\u0027Are you sure you want to delete this document?\u0027);\" style=\"color:Red;\"\u003eRemove\u003c/a\u003e",
"field": "ID",
"encoded": true
}, {
"width": "80px",
"command": [{
"name": "edit",
"buttonType": "ImageAndText",
"text": "Edit"
}]
}],
"pageable": {
"pageSizes": [5, 10, 20],
"buttonCount": 5
},
"sortable": true,
"selectable": "Single, Cell",
"resizable": true,
"scrollable": false,
"editable": {
"confirmation": "Are you sure you want to delete this record?",
"confirmDelete": "Delete",
"cancelDelete": "Cancel",
"mode": "inline",
"create": true,
"update": true,
"destroy": true
},
"messages": {
"noRecords": "No records available."
},
"dataSource": {
"type": (function() {
if (kendo.data.transports['aspnetmvc-ajax']) {
return 'aspnetmvc-ajax';
} else {
throw new Error('The kendo.aspnetmvc.min.js script is not included.');
}
})(),
"transport": {
"read": {
"url": ""
},
"prefix": "",
"update": {
"url": "/Blurb/DocAttributeUpdate"
}
},
"pageSize": 20,
"page": 1,
"total": 3,
"error": error_handler,
"schema": {
"data": "Data",
"total": "Total",
"errors": "Errors",
"model": {
"id": "ID",
"fields": {
"ID": {
"editable": false,
"type": "number"
},
"ClientId": {
"type": "number"
},
"SortOrder": {
"editable": false,
"type": "number",
"defaultValue": null
},
"DisplayText": {
"type": "string"
},
"Type": {
"type": "string"
},
"MimeType": {
"type": "string"
},
"FileName": {
"editable": false,
"type": "string"
},
"Document": {
"type": "object"
}
}
}
},
"data": {
"Data": [{
"ID": 440,
"ClientId": 16,
"DisplayText": "Test Document",
"FileName": "3182AscensionRecipientsDashboard (5).pdf",
"Type": "Document",
"MimeType": "application/pdf",
"Document": {
"ID": 0,
"DocumentAttributeId": 0,
"FileContent": null ,
"Content": null
},
"SortOrder": 0
}, {
"ID": 5,
"ClientId": 16,
"DisplayText": "Summary Plan Description",
"FileName": "Summary Plan Description.pdf",
"Type": "Document",
"MimeType": "application/pdf",
"Document": {
"ID": 0,
"DocumentAttributeId": 0,
"FileContent": null ,
"Content": null
},
"SortOrder": 1
}, {
"ID": 6,
"ClientId": 16,
"DisplayText": "Summary Annual Report",
"FileName": "SUMMARY ANNUAL REPORT.pdf",
"Type": "Document",
"MimeType": "application/pdf",
"Document": {
"ID": 0,
"DocumentAttributeId": 0,
"FileContent": null ,
"Content": null
},
"SortOrder": 2
}],
"Total": 3,
"AggregateResults": null
}
}
});
});
</script>

I had to approach edit a bit differently to get this work, although I might still try to figure out why my original way wasn't working.
I had to add the toolbar feature of kendo and make the cell editable:
.ToolBar(toolBar =>
{
toolBar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))

Related

JSON only reading first element of array

I am working on a discord bot using Typescript, and I am having a problem reading from the config.JSON file.
This is the read vars function:
fs.readFile('config.json', 'utf8', function readFileCallback(err, data){
if (err){
console.log(err);
} else {
config = JSON.parse(data);
console.log(config);
const store = config.configstore[0];
roster = config.roster[0];
}});
and this is the config.json file:
{
"configstore": [
{"prefix": "!!"},
{"wallTime": 5},
{"bufferTime": 15},
{"wall": "false"},
{"buffer": "false"},
{"lastWallTime": "-1"},
{"lastBufferTime": "-1"},
{"wallCheckRole": "Role"},
{"bubfferCheckRole": "Role"}
],
"roster": [
{"discID":"discordID","ign":"IGN"}
]
}
When I print out the raw 'config' variable it prints this:
{
configstore: [
{ prefix: '!!' },
{ wallTime: 5 },
{ bufferTime: 15 },
{ wall: 'false' },
{ buffer: 'false' },
{ lastWallTime: '-1' },
{ lastBufferTime: '-1' },
{ wallCheckRole: 'Role' },
{ bubfferCheckRole: 'Role' }
],
roster: [ { discID: 'DiscordID', ign: 'IGN' } ]
}
But when I print the store variable it prints this:
{ prefix: '!!' }
The roster is normal as well.
The roles and ids are strings, but I changed it since I don't want them leaked.
These are some examples of what you are probably trying to achieve:
let config1 = {
"configstore": [
{"prefix": "!!"},
{"wallTime": 5},
{"bufferTime": 15},
{"wall": "false"},
{"buffer": "false"},
{"lastWallTime": "-1"},
{"lastBufferTime": "-1"},
{"wallCheckRole": "Role"},
{"bubfferCheckRole": "Role"}
],
"roster": [
{"discID":"discordID","ign":"IGN"}
]
}
let config2 = {
"configstore": [
{
"prefix": "!!",
"wallTime": 5,
"bufferTime": 15,
"wall": "false",
"buffer": "false",
"lastWallTime": "-1",
"lastBufferTime": "-1",
"wallCheckRole": "Role",
"bubfferCheckRole": "Role"
}
],
"roster": [
{"discID":"discordID","ign":"IGN"}
]
}
//prints {"prefix":"!!"}
console.log("configstore1:", JSON.stringify(config1.configstore[0]));
//prints {"discID":"discordID","ign":"IGN"}
console.log("roster1:", JSON.stringify(config1.roster[0]));
//prints {"prefix":"!!","wallTime":5,"bufferTime":15,"wall":"false","buffer":"false","lastWallTime":"-1","lastBufferTime":"-1","wallCheckRole":"Role","bubfferCheckRole":"Role"}
console.log("configstore2:", JSON.stringify(config2.configstore[0]));
//prints {"discID":"discordID","ign":"IGN"}
console.log("roster2:", JSON.stringify(config2.roster[0]));

setstate() with list.lengh parameter didn't work

I tried to count the number of items in my list "data"
my component looks like that :
BuildMap() {
axios.post('http://104.xx.xx.xxx:8081/children', {action: "list"}, {headers: {'x-access-token': this.props.base.Token}})
.then(res => {
const data = res.data;
this.setState({data, NbrProfil: data.length});
})
.catch(err => console.log(err));
}
"data" is correctly returned and here is what it's return :
[
{
"name": "Mia",
"age": 12,
"options": [],
"discordId": "12",
"alerts": 0,
"warnings": 0
},
{
"name": "Demetra",
"age": 12,
"options": [],
"discordId": "12",
"alerts": 0,
"warnings": 0
}
]
sadly "NbrProfil" stay undefined and could be "2" ...
can I have some help please ?

{this.state.object} Objects are not valid as a React child

I have a response json like this:
{
"variables": {
"lock": 0,
"pos": 55,
"pos_on": 55,
"pos_off": 150
},
"id": "11",
"name": "Lock_table_2",
"hardware": "esp8266",
"connected": true
}
and I try to show the lock value in 'variables' object
so I write
constructor(props) {
super(props)
this.state = {
dock_1: {}, // define a empty json
dock_2: {},
dock_3: {},
}
}
pingIP() {
axios
.get('http://192.168.50.225:8888/test_check')
.then(response => {
let data = response.data.list; // return value is a list
this.setState({ // every 2 sec setState
dock_1: data[0], // data[0] -> 192.168.50.40's json
dock_2: data[1],
dock_3: data[2],
})
})
}
render(){
return (
<p>{this.state.dock_1.variables.lock}</p>
);
}
but I got this error
in here
So I tried this
render(){
return (
<p>{this.state.dock_1.variables}</p>
);
}
then here comes the another error message
in here
here is the get request return value
{
"list": [
{
"connected": true,
"hardware": "esp8266",
"id": "10",
"name": "Lock_table_1",
"variables": {
"lock": 1,
"pos": 80,
"pos_off": 160,
"pos_on": 80
}
},
{
"connected": true,
"hardware": "esp8266",
"id": "10",
"name": "Lock_table_2",
"variables": {
"lock": 1,
"pos": 80,
"pos_off": 160,
"pos_on": 80
}
},
{
"connected": true,
"hardware": "esp8266",
"id": "10",
"name": "Lock_table_3",
"variables": {
"lock": 1,
"pos": 80,
"pos_off": 160,
"pos_on": 80
}
}
]
}
the return value is a list
in order to get first value so I wrote data[0], data1 ...
what's happening in here?
I think your response is an array of 3 items like this:
[
{
variables: {
lock: 0,
pos: 55,
pos_on: 55,
pos_off: 150
},
id: "11",
name: "Lock_table_2",
hardware: "esp8266",
connected: true
},
{
variables: {
lock: 1,
pos: 44,
pos_on: 56,
pos_off: 151
},
id: "11",
name: "Lock_table_3",
hardware: "esp8267",
connected: false
},
{
variables: {
lock: 2,
pos: 45,
pos_on: 57,
pos_off: 152
},
id: "11",
name: "Lock_table_4",
hardware: "esp8268",
connected: true
}
]
So you can access the dock 1 variable lock using Inline If with Logical && Operator to prevent null exception.
<p>{this.state.dock_1.variables && this.state.dock_1.variables.lock}</p>
A sample working codesandbox with a fake api:
https://codesandbox.io/s/stoic-chaplygin-r1yxd

How to render list of hundreds of Images using FlatList and JSON data

Hi I would like to learn how I can map() through this JSON and grab the href of each image and place into a FlatList?
Currently the information I am trying to grab is collection.items.links[0].href and would like to place this href into the Image uri
The problem is I can grab one image easy and place it into a FlatList, but cannot work out how I can grab all of them and render a list of hundreds of images using the FlatList. This is because somehow I need to use map() at this point it seems:
collection.items map() .links[0].href
Thank you in advance!
Example of Json
{
"collection": {
"links": [
{
"prompt": "Next",
"rel": "next",
"href": "https://images-api.nasa.gov/search?media_type=image&q=moon&page=2"
}
],
"version": "1.0",
"metadata": {
"total_hits": 6726
},
"items": [
{
"links": [
{
"render": "image",
"rel": "preview",
"href": "https://images-assets.nasa.gov/image/PIA12235/PIA12235~thumb.jpg"
}
],
"data": [
{
"nasa_id": "PIA12235",
"secondary_creator": "ISRO/NASA/JPL-Caltech/Brown Univ.",
"keywords": [
"Moon",
"Chandrayaan-1"
],
"date_created": "2009-09-24T18:00:22Z",
"media_type": "image",
"title": "Nearside of the Moon",
"description_508": "Nearside of the Moon",
"center": "JPL",
"description": "Nearside of the Moon"
}
],
"href": "https://images-assets.nasa.gov/image/PIA12235/collection.json"
},
{
"links": [
{
"render": "image",
"rel": "preview",
"href": "https://images-assets.nasa.gov/image/PIA13517/PIA13517~thumb.jpg"
}
],
"data": [
{
"nasa_id": "PIA13517",
"secondary_creator": "NASA/GSFC/Arizona State University",
"keywords": [
"Moon",
"Lunar Reconnaissance Orbiter LRO"
],
"date_created": "2010-09-10T22:24:40Z",
"media_type": "image",
"title": "Color of the Moon",
"description_508": "Color of the Moon",
"center": "JPL",
"description": "Color of the Moon"
}
],
"href": "https://images-assets.nasa.gov/image/PIA13517/collection.json"
},
{
"links": [
{
"render": "image",
"rel": "preview",
"href": "https://images-assets.nasa.gov/image/PIA12233/PIA12233~thumb.jpg"
}
],
"data": [
{
"nasa_id": "PIA12233",
"secondary_creator": "NASA/JPL-Caltech",
"keywords": [
"Moon",
"Chandrayaan-1"
],
"date_created": "2009-09-24T18:00:20Z",
"media_type": "image",
"title": "Mapping the Moon, Point by Point",
"description_508": "Mapping the Moon, Point by Point",
"center": "JPL",
"description": "Mapping the Moon, Point by Point"
}
],
"href": "https://images-assets.nasa.gov/image/PIA12233/collection.json"
},
{
"links": [
{
"render": "image",
"rel": "preview",
"href": "https://images-assets.nasa.gov/image/PIA12228/PIA12228~thumb.jpg"
}
],
"data": [
{
"nasa_id": "PIA12228",
"secondary_creator": "NASA/JPL-Caltech/USGS",
"keywords": [
"Moon",
"Cassini-Huygens"
],
"date_created": "2009-09-24T18:00:15Z",
"media_type": "image",
"title": "Cassini Look at Water on the Moon",
"description_508": "Cassini Look at Water on the Moon",
"center": "JPL",
"description": "Cassini Look at Water on the Moon"
}
],
"href": "https://images-assets.nasa.gov/image/PIA12228/collection.json"
},
Also here is my code:
export default class ThirdScreen extends React.Component {
state = {
search: "",
data: "",
}
fetchNasa = () => {
const {search} = this.state;
fetch(`https://images-api.nasa.gov/search?q=${search}&media_type=image`)
.then((response) => response.json())
.then((result) => this.setState({
data: result.collection.items[0].links[0].href
}))
}
renderItem = ({item}) => {
return (
<View>
<TouchableOpacity
style={{margin: 5, backgroundColor: 'black', padding: 15}}
>
<Image
source={{uri: this.state.data}}
style={{width: 60, height: 60}}
/>
</TouchableOpacity>
</View>
)
}
render() {
const {data} = this.state
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<FlatList
data={data}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
In JavaScript, Array.map() takes a function that takes each item of the original array and returns the new item that replaces it. You can use it to transform arrays from one structure to another. For example, you can transform the JSON data in your post from its original, complicated form to simply an array of strings of the HREFs:
const data = result.collection.items.map(eachItem => {
return Array.isArray(eachItem.links) && eachItem.links[0] && eachItem.links[0].href
});
Now plug something like that into your fetchNasa function so that your data variable in state is an array of strings representing HREFs:
fetchNasa = () => {
const {search} = this.state;
fetch(`https://images-api.nasa.gov/search?q=${search}&media_type=image`)
.then((response) => response.json())
.then((result) => this.setState({
data: result.collection.items.map(eachItem => {
return Array.isArray(eachItem.links) && eachItem.links[0] && eachItem.links[0].href
})
}));
}
Finally, renderItem should use the item passed to it as an argument in order to return what to render. In fact, renderItem is essentially a version of an Array.map function: it takes each item of the original data structure and returns some kind of React elements to render:
renderItem = ({item}) => {
return (
<View>
<TouchableOpacity
style={{margin: 5, backgroundColor: 'black', padding: 15}}
>
<Image
source={{uri: item}}
style={{width: 60, height: 60}}
/>
</TouchableOpacity>
</View>
)
}
Because each item in your this.state.data array is a string representing an HREF, you can pass that directly into your <Image> source prop as the URI.

JQuery Grid-SubGrid for Parent-Child relation

I need some idea, about how to implement a subgrid in the following sceaniro.
The following is the json data that I want to display in the JQuery Grid and Subgrid.
Basically I am getting an object called "Contact" that has a collection called "actionSet".
{
"total" : "10",
"page" : "1",
"records" : "78",
"rows" : [ {
"comment" : null,
"givenName" : "Contact A",
"familyName" : "A",
"actionSet" : [ {
"actionID" : 1,
"actionDueDate" : "2012-12-08",
"actionNote" : "Action 1"
}, {
"actionID" : 2,
"actionDueDate" : "2012-12-08",
"actionNote" : "Action 2"
} ]
} ...]
}
I want eache Grid row to display the "Contact" and the subgris associated with the grid should display "actionSet" collection.
When a particular row in the Grid is selected, I do not want to make a server call to get the associated actions, as they are allready present in the "actionSet".
I have got the Grid working, displaying the "Contacts" nicely, but I get confused while implement the subgrid, as how to get the data for it, as its allready available in json.
jq(function() {
jq("#grid").jqGrid({
url:'/smallworks/project/getall.do',
datatype: 'json',
mtype: 'GET',
colNames:['Id', 'First Name', 'Last Name'],
colModel:[
{name:'id',index:'id', width:55,editable:false,editoptions: {readonly:true,size:10},hidden:true},
{name:'givenName',index:'givenName', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}},
{name:'familyName',index:'familyName', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}}
],
postData: {
},
rowNum:20,
rowList:[20,40,60],
height: 200,
autowidth: true,
rownumbers: true,
pager: '#pager',
sortname: 'id',
viewrecords: true,
sortorder: "asc",
caption:"Contacts",
emptyrecords: "Empty records",
loadonce: false,
loadComplete: function() {
},
Is this achievable?
Do I need to parse JSON data specially for the subgrid?
How can this be achieved?
I suggest that you save information from actionSet in an object which you can easy access later. For example you can use userData parameter and fill the userdata part of JSON data inside of beforeProcessing. The create subgrid you can follow the answer or another one.
The demo demonstrate the implementation approach:
It uses the following code
var mainGridPrefix = "s_";
$("#grid").jqGrid({
url: "Adofo.json",
datatype: "json",
colNames: ["First Name", "Last Name"],
colModel: [
{ name: "givenName" },
{ name: "familyName" }
],
cmTemplate: {width: 100, editable: true, editrules: {required: true},
editoptions: {size: 10}},
rowNum: 20,
rowList: [20, 40, 60],
pager: "#pager",
gridview: true,
caption: "Contacts",
rownumbers: true,
autoencode: true,
height: "100%",
idPrefix: mainGridPrefix,
subGrid: true,
jsonReader: { repeatitems: false },
beforeProcessing: function (data) {
var rows = data.rows, l = rows.length, i, item, subgrids = {};
for (i = 0; i < l; i++) {
item = rows[i];
if (item.actionSet) {
subgrids[item.id] = item.actionSet;
}
}
data.userdata = subgrids;
},
subGridRowExpanded: function (subgridDivId, rowId) {
var $subgrid = $("<table id='" + subgridDivId + "_t'></table>"),
pureRowId = $.jgrid.stripPref(mainGridPrefix, rowId),
subgrids = $(this).jqGrid("getGridParam", "userData");
$subgrid.appendTo("#" + $.jgrid.jqID(subgridDivId));
$subgrid.jqGrid({
datatype: "local",
data: subgrids[pureRowId],
colNames: ["Due Date", "Note"],
colModel: [
{ name: "actionDueDate", formatter: "date", sorttype: "date" },
{ name: "actionNote" }
],
sortname: "actionDueDate",
height: "100%",
rowNum: 10000,
autoencode: true,
autowidth: true,
jsonReader: { repeatitems: false, id: "actionID" },
gridview: true,
idPrefix: rowId + "_"
});
}
});
UPDATED: The JSON data used in the demo one can see below. I added id property which is required for jqGrid. I used actionID as the id of the subgrids:
{
"total": "10",
"page": "1",
"records": "78",
"rows": [
{
"id": 10,
"comment": null,
"givenName": "Contact A",
"familyName": "A",
"actionSet": [
{
"actionID": 1,
"actionDueDate": "2012-12-08",
"actionNote": "Action 1"
},
{
"actionID": 2,
"actionDueDate": "2012-12-09",
"actionNote": "Action 2"
}
]
},
{
"id": 20,
"comment": null,
"givenName": "Contact B",
"familyName": "B",
"actionSet": [
{
"actionID": 3,
"actionDueDate": "2012-12-11",
"actionNote": "Action 3"
},
{
"actionID": 4,
"actionDueDate": "2012-12-10",
"actionNote": "Action 4"
}
]
}
]
}