grid.get_masterTableView().rebind() not firing after any of the following process:
Insert
Delete
Update
Leaving me to manually refreshing the page before seeing the updates inside the grid. I'm doing client side dataBinding and using the ClientDataSource.
I'm not sure if it is my coding giving the problem or there is a bug in both later versions of the Telerik UI for ASP.Net AJAX 2014 (Q2 - 2104.2.618 and Q3 - 2014.3.1209)
I'm attaching the link to my projects for you to review.
https://drive.google.com/folderview?id=0BzWUZQhT9G4oZWwyN2NNcEJBUXc&usp=sharing
Anticipating a speedy response.
Thanks you
5 Answers, 1 is accepted
In order to bind RadGrid to a RadClientDataSource control should follow the approach illustrated in the following online demo.
Note how the CRUD operations are handled by the service. The Select, Update, Insert and Delete methods are specified in the WebServiceDataSourceSettings of RadClientDataSource.
Regards,Viktor Tachev
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Protected
Sub
Page_Load(sender
As
Object
, e
As
EventArgs)
Handles
Me
.Load
End
Sub
Public
Class
StudentRec
Private
_ID
As
String
Private
_Name
As
String
Private
_TotalMarks
As
Integer
Public
Sub
Student(
ByVal
id
As
String
,
ByVal
name
As
String
,
ByVal
tMarks
As
Integer
)
Me
._ID = id
Me
._Name = name
Me
._TotalMarks = tMarks
End
Sub
Public
Property
ID()
As
String
Get
Return
Me
._ID
End
Get
Set
(value
As
String
)
Me
._ID = value
End
Set
End
Property
Public
Property
Name()
As
String
Get
Return
Me
._Name
End
Get
Set
(value
As
String
)
Me
._Name = value
End
Set
End
Property
Public
Property
TotalMarks()
As
Integer
Get
Return
Me
._TotalMarks
End
Get
Set
(value
As
Integer
)
Me
._TotalMarks = value
End
Set
End
Property
End
Class
<WebMethod()> _
Public
Shared
Function
GetStudByID(
ByVal
studID
As
String
)
As
StudentRec
Dim
stud
As
New
StudentRec()
Dim
SqlCon
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
"ConString"
).ConnectionString)
Dim
SqlCmd
As
New
SqlCommand(
"Select ID, Name, TotalMarks from Student where ID = @ID"
, SqlCon)
SqlCon.Open()
SqlCmd.Parameters.AddWithValue(
"@ID"
, studID)
'Loop through the database until the page where the record is located is identified.
Dim
SqlRdr
As
SqlDataReader = SqlCmd.ExecuteReader()
While
SqlRdr.Read()
Dim
i
As
Integer
= 0
While
i < SqlRdr.FieldCount
Select
Case
SqlRdr.GetName(i)
Case
"ID"
stud.ID = (SqlRdr.GetString(i))
Exit
Select
Case
"Name"
stud.Name = (SqlRdr.GetString(i))
Exit
Select
Case
"TotalMarks"
stud.TotalMarks = Convert.ToInt32(SqlRdr(i))
Exit
Select
End
Select
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
End
While
End
While
SqlRdr.Close()
SqlCon.Close()
Return
stud
End
Function
<WebMethod()> _
Public
Shared
Function
AddStudent(
ByVal
stud
As
StudentRec)
As
Pair
Dim
result
As
New
Pair
Dim
SqlCon
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
"ConString"
).ConnectionString)
result.Second =
"RgStud"
'Dim FileInfo As New Pair
Dim
SqlCmd
As
New
SqlCommand(
"Insert Into Student Values(@id,@name,@marks)"
, SqlCon)
SqlCon.Open()
SqlCmd.Parameters.AddWithValue(
"@id"
, stud.ID)
SqlCmd.Parameters.AddWithValue(
"@name"
, stud.Name)
SqlCmd.Parameters.AddWithValue(
"@marks"
, stud.TotalMarks)
Try
SqlCmd.ExecuteNonQuery()
Catch
ex
As
Exception
If
Not
ex.InnerException
Is
Nothing
Then
If
ex.InnerException.Message.Contains(
"Violation of PRIMARY KEY constraint"
)
Then
result.First =
"There is already an Student ID in the database."
Else
result.First = ex.InnerException.Message.Replace(
"'"
,
"'"
)
End
If
Else
result.First = ex.Message.Replace(
"'"
,
"'"
)
End
If
Return
result
Finally
SqlCon.Close()
End
Try
result.First =
"Ok"
Return
result
End
Function
<WebMethod()> _
Public
Shared
Function
UpdateStudent(
ByVal
stud
As
StudentRec)
As
Pair
Dim
result
As
New
Pair
Dim
SqlCon
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
"ConString"
).ConnectionString)
result.Second =
"RgStud"
Dim
SqlCmd
As
New
SqlCommand(
"UPDATE Student SET Name=@name,TotalMarks=@marks WHERE ID=@id"
, SqlCon)
SqlCon.Open()
SqlCmd.Parameters.AddWithValue(
"@id"
, stud.ID)
SqlCmd.Parameters.AddWithValue(
"@name"
, stud.Name)
SqlCmd.Parameters.AddWithValue(
"@marks"
, stud.TotalMarks)
Try
SqlCmd.ExecuteNonQuery()
Catch
ex
As
Exception
If
Not
ex.InnerException
Is
Nothing
Then
If
ex.InnerException.Message.Contains(
"Violation of PRIMARY KEY constraint"
)
Then
result.First =
"There is already an Student ID in the database."
Else
result.First = ex.InnerException.Message.Replace(
"'"
,
"'"
)
End
If
Else
result.First = ex.Message.Replace(
"'"
,
"'"
)
End
If
Return
result
Finally
SqlCon.Close()
End
Try
result.First =
"Ok"
Return
result
End
Function
<WebMethod()> _
Public
Shared
Function
DeleteStudent(
ByVal
studID
As
String
)
As
Pair
'Delete the selected row from the grid
Dim
result
As
New
Pair
Dim
SqlCon
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
"ConString"
).ConnectionString)
result.Second =
"RgStud"
Dim
SqlCmd
As
New
SqlCommand(
"DELETE Student WHERE ID=@ID"
, SqlCon)
SqlCon.Open()
SqlCmd.Parameters.AddWithValue(
"@ID"
, studID)
Try
SqlCmd.ExecuteNonQuery()
Catch
ex
As
Exception
If
Not
ex.InnerException
Is
Nothing
Then
If
ex.InnerException.Message.Contains(
"File does not exist"
)
Then
result.First =
"Record does not exist."
Else
result.First = ex.InnerException.Message.Replace(
"'"
,
"'"
)
End
If
Else
result.First = ex.Message.Replace(
"'"
,
"'"
)
End
If
Return
result
Finally
SqlCon.Close()
End
Try
result.First =
"Ok"
Return
result
End
Function
<WebMethod> _
Public
Shared
Function
GetStudIndex(
ByVal
studID
As
String
)
As
Integer
Dim
SqlCon
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
"ConString"
).ConnectionString)
Dim
SqlCmd
As
New
SqlCommand(
"SELECT COUNT(ID) As RecordNumber FROM Student WHERE ID <= @ID"
, SqlCon)
SqlCmd.Parameters.AddWithValue(
"@ID"
, studID)
SqlCon.Open()
Dim
i
As
Integer
= SqlCmd.ExecuteScalar()
SqlCon.Close()
Return
i
End
Function
Client-Side coding
//Radgrid
var
RgStud;
//Master Table View
var
masterTable;
//DataKeyName
var
studID;
//RadTextBox control names
var
RtbID;
var
RtbName;
var
RntbMarks;
//Item index
var
itemIndex;
//stores last command name
var
lastCommand;
//Stores radgrid page index
var
pageIndex;
var
newPage;
function
ParseData(sender, args) {
var
response = args.get_response().d;
if
(response) {
args.set_parsedData(response.Data);
}
}
function
Rg_GridCreated(sender, args) {
var
grid = $find(sender.get_element().id);
var
gridName = grid.get_id();
switch
(gridName) {
case
"RgStud"
:
RgStud = grid;
masterTable = grid.get_masterTableView();
break
;
default
:
radalert(
"No RadGrid was found "
+ grid.get_id(), 330, 110,
"Debug"
);
}
}
$(document).ready(
function
() {
$(
"#BtnAdd"
).click(
function
() {
UpdateInsert($(
"#BtnAdd"
));
});
})
function
UpdateInsert(button) {
if
(button.val() ==
"Insert"
) {
AddStudent();
}
else
if
(button.val() ==
"Update"
) {
UpdateStudent();
}
}
//Handle result
function
handleResult(result) {
if
(result.First ==
"Ok"
) {
setTimeout(
function
() {
masterTable.rebind();
}, 300);
switch
(lastCommand) {
case
"InitInsert"
:
case
"Edit"
:
setTimeout(
function
() {
PageMethods.GetStudIndex(studID, locateRecord);
}, 300);
break
;
case
"DeleteClient"
:
locateRecord(newPage);
break
;
default
:
}
}
else
{
radalert(result.First, 330, 140,
"Error"
);
}
}
//Go to the page index and select the record
function
locateRecord(page) {
if
(page > 0) {
var
mtv = RgStud.get_masterTableView()
var
pageSize = mtv.get_pageSize();
pageIndex = Math.ceil(page / pageSize);
var
recordIndex = (page - 1) % pageSize;
setTimeout(
function
() {
mtv.page(pageIndex);
}, 300);
mtv.selectItem(mtv.get_dataItems()[recordIndex].get_element());
}
else
radalert(
"Record not found:"
,330,110,
"Search Complete"
);
}
//Go to the page index and select the record above deleted record
function
RecordAbove(page) {
if
(page <= 1)
newPage = page;
else
newPage = page - 1;
}
var
student = {
ID:
null
, Name:
null
, TotalMarks:
null
,
create:
function
() {
var
obj =
new
Object();
obj.ID =
""
;
obj.Name =
""
;
obj.TotalMarks =
""
;
}
};
function
AddStudent() {
PageValidators(
true
);
if
(Page_IsValid) {
PageValidators(
false
);
student.ID = RtbID.get_value();
studID = RtbID.get_value();
student.Name = RtbName.get_value();
student.TotalMarks = RntbMarks.get_value();
PageMethods.AddStudent(student, handleResult);
CancelStud();
}
}
//Bind selected budgetObject record to controls
function
setValues(student) {
RtbID.set_value(student.ID);
RtbName.set_value(student.Name);
RntbMarks.set_value(student.TotalMarks);
RtbID._textBoxElement.readOnly =
true
;
}
//Update budgetObject record client-side
function
UpdateStudent() {
PageValidators(
true
);
if
(Page_IsValid) {
PageValidators(
false
);
student.ID = RtbID.get_value();
studID = RtbID.get_value();
student.Name = RtbName.get_value();
student.TotalMarks = RntbMarks.get_value();
PageMethods.UpdateStudent(student, handleResult);
CancelStud();
}
}
function
CancelStud() {
//Close form
PageValidators(
false
);
$(
"#divForm"
).fadeOut();
$(
"#divTable"
).fadeIn();
setTimeout(
function
() {
$(
"#divForm"
).css(
"position"
,
"absolute"
);
}, 200);
setTimeout(
function
myfunction() {
RtbID.set_value(
''
);
RtbName.set_value(
''
);
RntbMarks.set_value(
'0'
);
}, 500);
}
function
Rg_OnCommand(sender, args) {
args.set_cancel(
true
);
itemIndex = args.get_commandArgument();
lastCommand = args.get_commandName();
switch
(args.get_commandName()) {
case
"InitInsert"
:
$(
"#BtnAdd"
).attr(
'value'
,
'Insert'
);
setTimeout(
function
myfunction() {
$(
"#divForm"
).fadeIn();
$(
"#divTable"
).hide();
$(
"#divForm"
).css(
"position"
,
"static"
);
}, 500);
RtbID._textBoxElement.readOnly =
false
;
break
;
case
"DeleteClient"
:
//Remove the row in question and refresh the list for this page.
studID = args.get_tableView().get_dataItems()[args.get_commandArgument()].getDataKeyValue(
"ID"
);
radconfirm(
"Are you sure you wish to remove this Student record ID '<em>"
+ studID +
"</em>'? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
PageMethods.GetStudIndex(studID, RecordAbove);
PageMethods.DeleteStudent(studID, handleResult);
}
}, 330, 150,
"Delete Confirmation"
);
//radalert(args.get_commandName(), 330, 110, "Debug");
break
;
case
"Edit"
:
$(
"#BtnAdd"
).attr(
'value'
,
'Update'
);
studID = args.get_tableView().get_dataItems()[args.get_commandArgument()].getDataKeyValue(
"ID"
);
PageMethods.GetStudByID(studID, setValues);
setTimeout(
function
myfunction() {
$(
"#divForm"
).fadeIn();
$(
"#divTable"
).hide();
$(
"#divForm"
).css(
"position"
,
"static"
);
}, 500);
break
;
default
:
}
}
//Cleint Load for RadTextBox
function
Rtb_OnLoad(sender, args) {
var
rtb_id = sender.get_id();
var
rtb_Name = rtb_id.substring(rtb_id.lastIndexOf(
'_'
) + 1, rtb_id.length);
switch
(rtb_Name) {
case
"RtbID"
:
RtbID = sender;
break
;
case
"RntbMarks"
:
RntbMarks = sender;
break
;
case
"RtbName"
:
RtbName = sender;
break
;
default
:
radalert(
"Unrecognized RadTextBox: "
+ rtb_Name, 330, 110,
"Debug"
);
}
}
//Enable/Disable validators for a particular data entry group
function
PageValidators(active) {
ValidatorEnable(document.getElementById(
"RpbStud_i0_rfvID"
), active);
ValidatorEnable(document.getElementById(
"RpbStud_i0_rfvName"
), active);
ValidatorEnable(document.getElementById(
"RpbStud_i0_rfvMarks"
), active);
}
WebForm
<
div
id
=
"divTable"
>
<
telerik:RadGrid
ID
=
"RgStud"
runat
=
"server"
AutoGenerateColumns
=
"False"
ClientDataSourceID
=
"RadStud"
AllowPaging
=
"true"
>
<
ClientSettings
>
<
ClientEvents
OnCommand
=
"Rg_OnCommand"
OnGridCreated
=
"Rg_GridCreated"
/>
</
ClientSettings
>
<
MasterTableView
ClientDataKeyNames
=
"ID"
DataKeyNames
=
"ID"
CommandItemDisplay
=
"Bottom"
>
<
Columns
>
<
telerik:GridEditCommandColumn
></
telerik:GridEditCommandColumn
>
<
telerik:GridBoundColumn
DataField
=
"ID"
ReadOnly
=
"True"
HeaderText
=
"ID"
SortExpression
=
"ID"
UniqueName
=
"ID"
FilterControlAltText
=
"Filter ID column"
>
<
ColumnValidationSettings
>
<
ModelErrorMessage
Text
=
""
></
ModelErrorMessage
>
</
ColumnValidationSettings
>
</
telerik:GridBoundColumn
>
<
telerik:GridBoundColumn
DataField
=
"Name"
HeaderText
=
"Name"
SortExpression
=
"Name"
UniqueName
=
"Name"
FilterControlAltText
=
"Filter Name column"
>
<
ColumnValidationSettings
>
<
ModelErrorMessage
Text
=
""
></
ModelErrorMessage
>
</
ColumnValidationSettings
>
</
telerik:GridBoundColumn
>
<
telerik:GridBoundColumn
DataField
=
"TotalMarks"
HeaderText
=
"TotalMarks"
SortExpression
=
"TotalMarks"
UniqueName
=
"TotalMarks"
DataType
=
"System.Int32"
FilterControlAltText
=
"Filter TotalMarks column"
>
<
ColumnValidationSettings
>
<
ModelErrorMessage
Text
=
""
></
ModelErrorMessage
>
</
ColumnValidationSettings
>
</
telerik:GridBoundColumn
>
<
telerik:GridButtonColumn
ButtonType
=
"PushButton"
Text
=
"Delete"
CommandName
=
"DeleteClient"
ConfirmDialogHeight
=
"125px"
ConfirmDialogType
=
"RadWindow"
ConfirmDialogWidth
=
"330px"
ConfirmText
=
"Are you sure you wish to delete this Student record?"
ConfirmTitle
=
"Delete Confirmation"
UniqueName
=
"BtnClientDelete"
>
<
HeaderStyle
Width
=
"30px"
/>
</
telerik:GridButtonColumn
>
</
Columns
>
</
MasterTableView
>
</
telerik:RadGrid
>
</
div
>
<
div
id
=
"divSpacer"
style
=
"display: none; z-index: 1; position: absolute; top: 26px; left: 0px; background-color: white"
> </
div
>
<
div
id
=
"divForm"
style
=
"display: none; z-index: 2; position: absolute; top: 0px; left: 0px; background-color: white"
>
<
telerik:RadPanelBar
runat
=
"server"
ID
=
"RpbStud"
Width
=
"100%"
CausesValidation
=
"True"
>
<
Items
>
<
telerik:RadPanelItem
runat
=
"server"
Expanded
=
"true"
>
<
ItemTemplate
>
<
table
cellspacing
=
"0"
cellpadding
=
"0"
width
=
"100%"
border
=
"0"
>
<
tr
>
<
td
style
=
"padding-top: 5px; text-align: right;"
>Student ID: </
td
>
<
td
colspan
=
"3"
style
=
"padding-top: 5px; padding-left: 5px;"
>
<
telerik:RadTextBox
ID
=
"RtbID"
runat
=
"server"
ClientEvents-OnLoad
=
"Rtb_OnLoad"
MaxLength
=
"5"
></
telerik:RadTextBox
>
<
asp:RequiredFieldValidator
ID
=
"rfvID"
runat
=
"server"
ControlToValidate
=
"RtbID"
ErrorMessage
=
"Student is required"
Enabled
=
"false"
CssClass
=
"errors"
Text
=
"ç"
ValidateEmptyText
=
"True"
></
asp:RequiredFieldValidator
>
</
td
>
</
tr
>
<
tr
>
<
td
style
=
"padding-top: 5px; text-align: right;"
>Student Name: </
td
>
<
td
colspan
=
"3"
style
=
"padding-top: 5px; padding-left: 5px;"
>
<
telerik:RadTextBox
ID
=
"RtbName"
runat
=
"server"
ClientEvents-OnLoad
=
"Rtb_OnLoad"
></
telerik:RadTextBox
>
<
asp:RequiredFieldValidator
ID
=
"rfvName"
runat
=
"server"
ControlToValidate
=
"RtbName"
ErrorMessage
=
"Student name is required"
Enabled
=
"false"
CssClass
=
"errors"
Text
=
"ç"
ValidateEmptyText
=
"True"
></
asp:RequiredFieldValidator
>
</
td
>
</
tr
>
<
tr
>
<
td
style
=
"padding-top: 5px; text-align: right;"
>Total Marks: </
td
>
<
td
colspan
=
"3"
style
=
"padding-top: 5px; padding-left: 5px;"
>
<
telerik:RadNumericTextBox
ID
=
"RntbMarks"
runat
=
"server"
ClientEvents-OnLoad
=
"Rtb_OnLoad"
></
telerik:RadNumericTextBox
>
<
asp:RequiredFieldValidator
ID
=
"rfvMarks"
runat
=
"server"
ControlToValidate
=
"RntbMarks"
ErrorMessage
=
"Username is required"
Enabled
=
"false"
CssClass
=
"errors"
Text
=
"ç"
ValidateEmptyText
=
"True"
></
asp:RequiredFieldValidator
>
</
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"4"
>
<
hr
/>
</
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"4"
style
=
"padding: 0px 5px 5px 5px;"
>
<
input
id
=
"BtnAdd"
type
=
"button"
value
=
"Insert"
/>
<
input
id
=
"BtnCncl"
type
=
"button"
value
=
"Cancel"
onclick
=
"CancelStud()"
/>
</
td
>
</
tr
>
</
table
>
</
ItemTemplate
>
</
telerik:RadPanelItem
>
</
Items
>
</
telerik:RadPanelBar
>
</
div
>
<
telerik:RadClientDataSource
ID
=
"RadStud"
runat
=
"server"
>
<
ClientEvents
OnDataParse
=
"ParseData"
/>
<
DataSource
>
<
WebServiceDataSourceSettings
BaseUrl
=
"StudService.svc/"
>
<
Select
Url
=
"GetStudent"
/>
</
WebServiceDataSourceSettings
>
</
DataSource
>
<
Schema
>
<
Model
ID
=
"ID"
>
<
telerik:ClientDataSourceModelField
FieldName
=
"ID"
DataType
=
"String"
/>
<
telerik:ClientDataSourceModelField
FieldName
=
"Name"
DataType
=
"String"
/>
<
telerik:ClientDataSourceModelField
FieldName
=
"TotalMark"
DataType
=
"Number"
/>
</
Model
>
</
Schema
>
</
telerik:RadClientDataSource
>
WCF Coding
Imports
System.Collections.Generic
Imports
System.Linq
Imports
System.Runtime.Serialization
Imports
System.ServiceModel
Imports
System.ServiceModel.Activation
Imports
System.ServiceModel.Web
Imports
System.Data.SqlClient
Imports
System.Web.HttpUtility
<ServiceKnownType(
GetType
(StudService.Student))> _
<ServiceContract> _
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>
Public
Class
StudService
<OperationContract> _
<WebGet> _
Public
Function
GetStudent()
As
StudResult
Dim
list
As
New
List(Of Student)
Dim
SqlConn
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
"ConString"
).ConnectionString)
Using SqlConn
Dim
SqlCmd
As
New
SqlCommand(
"SELECT * FROM Student ORDER BY ID"
, SqlConn)
SqlConn.Open()
Dim
reader
As
SqlDataReader = SqlCmd.ExecuteReader()
While
reader.Read()
Dim
stud
As
New
Student
Dim
i
As
Integer
= 0
While
i < reader.FieldCount
Select
Case
reader.GetName(i)
Case
"ID"
stud.ID = (reader.GetString(i))
Exit
Select
Case
"Name"
stud.Name = (reader.GetString(i))
Exit
Select
Case
"TotalMarks"
stud.TotalMarks = Convert.ToInt32(reader(i))
Exit
Select
End
Select
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
End
While
list.Add(stud)
End
While
reader.Close()
End
Using
Dim
sResult
As
New
StudResult
sResult.Data = list
sResult.Count = list.Count
Return
sResult
End
Function
<DataContract> _
Public
Class
Student
Private
_ID
As
String
Private
_Name
As
String
Private
_TotalMarks
As
Integer
Public
Sub
Student(
ByVal
id
As
String
,
ByVal
name
As
String
,
ByVal
tMarks
As
Integer
)
Me
._ID = id
Me
._Name = name
Me
._TotalMarks = tMarks
End
Sub
<DataMember> _
Public
Property
ID()
As
String
Get
Return
Me
._ID
End
Get
Set
(value
As
String
)
Me
._ID = value
End
Set
End
Property
<DataMember> _
Public
Property
Name()
As
String
Get
Return
Me
._Name
End
Get
Set
(value
As
String
)
Me
._Name = value
End
Set
End
Property
<DataMember> _
Public
Property
TotalMarks()
As
Integer
Get
Return
Me
._TotalMarks
End
Get
Set
(value
As
Integer
)
Me
._TotalMarks = value
End
Set
End
Property
End
Class
Public
Class
StudResult
Private
mData
As
List(Of Student)
Private
mCount
As
Integer
Public
Property
Data()
As
List(Of Student)
Get
Return
mData
End
Get
Set
(value
As
List(Of Student))
mData = value
End
Set
End
Property
Public
Property
Count()
As
Integer
Get
Return
mCount
End
Get
Set
(value
As
Integer
)
mCount = value
End
Set
End
Property
End
Class
End
Class
What I am trying to accomplished is that, upon insertion of a record, that new record be highlighted/selected. Same for updating.
And after deleting a record, the record above that deleted record would be highlighted/selected. However, grid.get_masterTableView().rebind() isn't firing that would refresh the grid showing whatever updates that would have been made.
Hope I have shed some light on what I wish to accomplish.
Thank you for your speedy response.
I have noticed that you are combining RadClientDataSource with manual CRUD operations, which will not allow you to accomplish your requirement. When using RadClientDataSource in combination with RadGrid, the CRUD operations should be handled through the RadClientDataSource control, as demonstrated in the following online demo:
As pointed previously, this is only supported with Batch Editing.
However, if you need to handle your CRUD operations manually, you will have to implement the approach demonstrated in the following online demo, where no RadClientDataSource control is used and the data is manually passed to the RadGrid:
Best Regards,
Konstantin Dikov
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Hello Konstantin,
What Raeshawn is asking is quite possible. I've actually accomplished the same thing using RadClientDataSource control and manual CRUD operations, very much like what Raeshawn has demonstrated. In fact, I have been doing it quite successfully until Q3 2014 when something changed.
Luckily, I managed to find a workaround. Calling the grid's
Raeshawn, I've looked at your code and I recommend that you change the following. Let's first look at your RadGrid_OnCommand function. I'm only going to show the code that I changed:
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
function
Rg_OnCommand(sender, args) {
//STEP 2: Modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
PageMethods.GetStudIndex(studID, RecordAbove);
PageMethods.DeleteStudent(studID, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid in Q2
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
RadGrid makes a call to Page(0) whenever it needs to refresh its view. This doesn't seem to work anymore since Q3 2014. This is why we handle it manually.
Finally, let's look at revisions to your handleResult function:
//Handle result
function
handleResult(result) {
if
(result ===
"Ok"
) {
setTimeout(
function
() {
masterTable.rebind();
}, 300);
//Paging forces the rebound grid to update itself post delete.
if
(recordDeleted) {
setTimeout(
function
() {
masterTable.page(pageIndex + 1);
}, 300);
}
switch
(lastCommand) {
case
"InitInsert"
:
case
"Edit"
:
setTimeout(
function
() {
PageMethods.GetStudIndex(studID, locateRecord);
}, 300);
break
;
default
:
}
}
}
Notice that I force the grid to go to a page that doesn't exist, thereby forcing it to update its list after a delete operation.
As you can see, the key change here is where a call to the RadGrid.Page command forces the grid to update the underlying list that it has been rebound to on the RadClientDataSource. This used to happen automatically up until Q3 2014. I can safely say that this work around will also run nicely in Q1 2015, SP1 and possibly Q2 - if the boys at Telerik don't change anything else.
Cheers,
Jonathan
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
//STEP 1: Declare a variable to flag record deletion
var
recordDeleted =
false
;
var
lastCommand;
function
Rg_OnCommand(sender, args) {
//STEP 2: modify the 'args.set_cancel(true);' line to ONLY cancel commands other than
// RebindGrid and Page - the latter of which we'll handle manually.
if
(args.get_commandName() !==
"RebindGrid"
|| args.get_commandName() !==
"Page"
)
args.set_cancel(
true
);
switch
(args.get_commandName()) {
case
"DeleteClient"
:
//Remove the row and refresh the list for this page.
radconfirm(
"Are you sure you wish to remove this student? This change cannot be undone."
,
function
confirm(arg) {
if
(arg ==
true
) {
//STEP 3: Add the flag in this DeleteClient block to track deletion
recordDeleted =
true
;
pageIndex = Rg.get_masterTableView().get_currentPageIndex();
PageMethods.DeleteRecord(trn, handleResult);
}
}, 350, 160,
"Delete Confirmation"
)
break
;
case
"Page"
:
//STEP 4: Add this 'Page' block to your switch control structure.
//Paging operations force the grid to update as it used to with RebindGrid
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
if
(!recordDeleted)
args.get_tableView().page(pageIndex);
else
{
args.get_tableView().page(pageIndex + 1);
recordDeleted =
false
;
}
}
break
;
}
}
Raeshawn,
If the grid is expected to be empty, you may have to further alter your RadGrid_OnCommand for the page command as follows:
case
"Page"
:
//BREAKING CHANGE: Telerik Q3 2014:
//Up until Telerik Q2 2014: Page 0 is usually called automatically after grid.rebind
//Now Page 0 is only called after a Page operation is forced by code.
//We must now handle paging operations manually as follows:
if
(args.get_commandArgument() == 0) {
args.set_cancel(
true
);
//...otherwise, full page reload occurs
var
mtv = Rg.get_masterTableView();
if
(recordDeleted ===
false
) {
//Record was added/edited. Page to force refresh
mtv.page(pageIndex + 1);
}
else
{
//Record was deleted
if
(mtv.get_dataItems().length === 1) {
//If it was the last item on page, go back one page.
mtv.page(mtv.get_currentPageIndex() - 1);
}
else
{
//Otherwise, go forward one page to force refresh.
mtv.page(pageIndex + 1);
}
recordDeleted =
false
;
}
}
break
;
This will take care of a bug where deleting the last record on a page will simply cause the grid to revert to its EmptyItemTemplate. This code forces the grid to go to the previous page if one exists.
Finally, we need to make changes to the handleResult function as well to take care of a situation where adding the FIRST record to a table doesn't show up until subsequent records are added:
//Handle result
function
handleResult(result) {
//alert(lastCommand);
if
(result !=
"Ok"
) {
radalert(result, 330, 140,
"Error"
);
}
else
{
setTimeout(
function
() {
var
mtv = RgStud.get_masterTableView();
mtv.rebind();
//Rebind grid.
//BREAKING CHANGE: Telerik Q3 2014: Rebind no longer auto updates the grid.
//The data won't show up until a page operation is forced.
//WORKAROUND: Force page operation to cause Page 0 command to update the grid.
if
(recordDeleted ===
false
) {
//A record was added/modified.
if
(mtv.get_dataItems().length === 0) {
//The very first record in the grid.
//Manually Set page index to 1 to hide the empty item template.
setTimeout(
function
() {
mtv.set_currentPageIndex(1);
}, 300);
}
else
{
//Records already exist. Since grid is now rebound,
//Page to refresh the item list.
pageIndex = mtv.get_currentPageIndex();
mtv.page(pageIndex + 1);
setTimeout(
function
() {
PageMethods.GetStudentIndex(studID, locateRecord);
}, 300);
}
closeForm();
}
else
{
//A record was deleted, Page to refresh the item list.
pageIndex = mtv.get_currentPageIndex();
mtv.page(pageIndex + 1);
}
}, 300);
}
}
As you can see, when the first record on the underlying datasource is added, the RadGrid page is not updated. You have to manually force set_currentPageIndex(1) to force it away from the Empty Item Template. Lastly, we have to modify the locateRecord function as follows:
//Go to the page index and select the record
function
locateRecord(page) {
var
mtv;
mtv = RgStud.get_masterTableView();
var
pageSize = mtv.get_pageSize();
pageIndex = Math.ceil((page) / pageSize);
var
recordIndex = (page - 1) % pageSize;
setTimeout(
function
() {
if
(pageIndex > mtv.get_pageCount()) {
//If we just deleted the last record on the page,
//we need to force a currentPageIndex update
setTimeout(
function
() {
mtv.set_currentPageIndex(pageIndex);
}, 300);
}
else
{
mtv.page(pageIndex);
}
}, 300);
mtv.selectItem(mtv.get_dataItems()[recordIndex].get_element());
}
This allows us to successfully navigate to previous pages after the last record on the current page is deleted. This is because since Q3 2014, this update no longer automatically takes place.
Hope this helps.
Jonathan.
//Go to the page index and select the record
function
locateRecord(page) {
var
mtv;
mtv = RgStud.get_masterTableView();
var
pageSize = mtv.get_pageSize();
pageIndex = Math.ceil((page) / pageSize);
var
recordIndex = (page - 1) % pageSize;
setTimeout(
function
() {
if
(pageIndex > mtv.get_pageCount()) {
//If we just deleted the last record on the page,
//we need to force a currentPageIndex update
setTimeout(
function
() {
mtv.set_currentPageIndex(pageIndex);
}, 300);
}
else
{
mtv.page(pageIndex);
}
}, 300);
mtv.selectItem(mtv.get_dataItems()[recordIndex].get_element());
}