ExtJS Modern Toolkit下Grid嵌套对象展示与子对象REST操作实现方案(基于RowExpander)
Solution for ExtJS Modern Grid with RowExpander and Child REST Operations
Got it, let's tackle this step by step. Since you're using the Modern Toolkit, RowExpander is exactly the right approach here. We'll set it up to display the movieRentals child records, then wire up the POST functionality for returning individual movies.
Step 1: Update the Parent Grid with RowExpander
First, let's fix your existing grid configuration—your original "Movie" column was pointing to a non-existent field, so we'll clean that up and add the RowExpander plugin to render child grids:
Ext.define('Vidly.view.rental.DisplayRentalsView', { extend: 'Ext.grid.Grid', xtype: 'displayrentalsview', reference: 'rentallist', title: 'Rental List', controller: 'displayrentalsviewcontroller', viewModel: 'rentalsviewmodel', reference:'displayrentalsviewgrid', selType: 'rowmodel', selModel: { mode: 'SINGLE' }, viewConfig: { stripeRows: true }, listeners: { selectionchange: 'onSelectionChange', show: 'onShow' }, bind: { store: '{RentalListStore}' }, itemConfig: { viewModel: true }, plugins: [ 'pagingtoolbar', { type: 'rowexpander', // Define the child grid that appears when expanding a parent row item: { xtype: 'grid', reference: 'childMovieGrid', columns: [ { text: "Movie Title", flex: 2, dataIndex: 'movie' }, { text: "Date Returned", flex: 1, dataIndex: 'dateReturned', renderer: function (value) { if (value) { return Ext.Date.format(new Date(value), 'm/d/Y'); } return 'Not Returned'; } }, { text: 'Actions', width: 120, cell: { tools: { returnMovie: { iconCls: 'x-fa fa-check-circle', tooltip: 'Return Movie', handler: 'onReturnMovieClick' } } } } ], // Bind the child grid's data to the parent record's movieRentals array bind: { store: '{record.movieRentals}' } } } ], items: [ { xtype: 'container', docked: 'top', items: [ { docked: 'left', xtype: 'button', ui: 'decline', itemId: 'returnRental', text: 'Return Rental', reference: 'btnReturnRental', handler: 'onReturnClick', disabled: true } ] } ], columns: [ { text: "Customer", flex: 1, dataIndex: 'customer' }, { text: "Date Rented", flex: 1, dataIndex: 'dateRented', renderer: function (value) { if (value) { return Ext.Date.format(new Date(value), 'm/d/Y'); } return ''; } } ] });
Step 2: Add Controller Logic for POST Operations
Next, update your displayrentalsviewcontroller to handle the return movie action, sending a POST request to your API and updating the local record on success:
Ext.define('Vidly.view.rental.DisplayRentalsViewController', { extend: 'Ext.app.ViewController', alias: 'controller.displayrentalsviewcontroller', // Keep your existing handlers here onSelectionChange: function() { /* Your existing code */ }, onShow: function() { /* Your existing code */ }, onReturnClick: function() { /* Your existing code */ }, // New handler for returning individual movies onReturnMovieClick: function(gridTool, cell) { // Grab the child movie rental record from the clicked cell const movieRecord = cell.getRecord(); const rentalId = movieRecord.get('rentalDetailDtoId'); const movieId = movieRecord.get('id'); // Prepare payload matching your API's requirements const postData = { id: movieId, rentalDetailDtoId: rentalId, dateReturned: new Date().toISOString() }; // Send POST request to your API endpoint Ext.Ajax.request({ url: '/api/movieRentals/return', // Replace with your actual API URL method: 'POST', jsonData: postData, success: (response) => { // Update the local record to reflect the returned status immediately movieRecord.set('dateReturned', postData.dateReturned); Ext.Msg.alert('Success', 'Movie marked as returned!'); }, failure: (response) => { Ext.Msg.alert('Error', 'Failed to process return. Please try again.'); } }); } });
Key Details Explained
- RowExpander Binding: The child grid's store is directly bound to the parent record's
movieRentalsarray using{record.movieRentals}, so it automatically loads the correct child data when a row is expanded. - Child Grid Actions: We added a tool button in the child grid's "Actions" column to trigger the return operation. The handler grabs the relevant record data, constructs the POST payload, and sends the request.
- Local Record Update: After a successful POST, we update the child record's
dateReturnedfield locally—no need to reload the entire store for instant feedback. - Column Cleanup: Removed invalid columns from the parent grid (since movie details belong to the child records) to keep the parent view focused on top-level rental info.
内容的提问来源于stack exchange,提问作者Samuel Marvin Aguilos
相关产品推荐
相关产品推荐

