This is a migrated thread and some comments may be shown as answers.

Radgrid rebind client side not working

4 Answers 353 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Raeshawn
Top achievements
Rank 1
Raeshawn asked on 29 Jan 2015, 09:27 PM
I'm currently using Q3 2014. I use clientdatasource as my datasource for my radgrid. If i'm editing a record client side, all works. However, when I'm inserting the first record inside the grid rebind() won't fire. I would have to manually refresh the page. 

Is there still some bugs inside Q3 that needs ironing or no one has experienced this problem?

Could anyone assist please?

Thank you.

4 Answers, 1 is accepted

Sort by
0
Konstantin Dikov
Telerik team
answered on 03 Feb 2015, 01:10 PM
Hello Raeshawn,

You can test the Update/Insert/Delete operations with RadGrid in Batch edit mode and RadClientDataSource control in the following demo and see that everything is working correctly with our latest version (Q3 2014 SP1), but the same behavior implementation was working correctly with Q3 2014:
Additionally, you can take a look at the manual CRUD operations with client-side binding in the following demo:
If you are using different approach in your project, please elaborate on the exact implementation, so we can have a better idea of the scenario.


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.

 
0
Raeshawn
Top achievements
Rank 1
answered on 04 Feb 2015, 01:50 PM
I am not doing batch edit, I am using WebMethods to Update/Insert/Delete.

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>



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.
0
Raeshawn
Top achievements
Rank 1
answered on 04 Feb 2015, 01:57 PM
This is the 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
0
Konstantin Dikov
Telerik team
answered on 09 Feb 2015, 11:27 AM
Hello Raeshawn,

Please refer to the answer in the other forum thread that you have opened:
For all sides convenience and for better tracking purposes, please try to avoid duplicate threads.


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.

 
Tags
Grid
Asked by
Raeshawn
Top achievements
Rank 1
Answers by
Konstantin Dikov
Telerik team
Raeshawn
Top achievements
Rank 1
Share this question
or