如何用Ember Power Select实现服务请求表格结果排序
Looks like you're almost there! The key issue with your current setup is that the model hook only runs once when the route loads—so changing selectedFilter via Power Select won't trigger a re-sort. Let's fix this by moving the sorting logic to a controller computed property (or tracked properties for Octane) so updates happen automatically.
Step 1: Simplify the Route's Model Hook
First, let the route just fetch the raw data without sorting—we'll handle that in the controller:
// app/routes/servicerequests/index.js model() { return this.store.findAll('servicerequest'); }
Step 2: Add Sorting Logic to the Controller
Classic Ember (Pre-Octane)
Use a computed property that reacts to changes in both the model array and selectedFilter:
// app/controllers/servicerequests/index.js import Controller from '@ember/controller'; import { computed } from '@ember/object'; export default class ServicerequestsIndexController extends Controller { // Adjust your filter options to include a display label and field value filterOptions = [ { label: 'Creation Date', value: 'createdAt' }, { label: 'Request Status', value: 'status' }, { label: 'Priority Level', value: 'priority' } ]; // Default sort field selectedFilter = 'createdAt'; @computed('model.[]', 'selectedFilter') get sortedServiceRequests() { if (!this.model) return []; // Sort by the selected field and reverse (as you had before) return this.model.sortBy(this.selectedFilter).reverse(); } }
Ember Octane (Modern)
If you're using Octane, use tracked properties and the built-in sort computed macro for cleaner code:
// app/controllers/servicerequests/index.js import Controller from '@ember/controller'; import { tracked } from '@glimmer/tracking'; import { sort } from '@ember/object/computed'; export default class ServicerequestsIndexController extends Controller { filterOptions = [ { label: 'Creation Date', value: 'createdAt' }, { label: 'Request Status', value: 'status' }, { label: 'Priority Level', value: 'priority' } ]; @tracked selectedFilter = 'createdAt'; @tracked isAscending = false; // Add this if you want to toggle sort direction // Dynamically build sort properties sortProperties = computed('selectedFilter', 'isAscending', function() { const direction = this.isAscending ? 'asc' : 'desc'; return [`${this.selectedFilter}:${direction}`]; }); // Auto-sorted array @sort('model', 'sortProperties') sortedServiceRequests; }
Step 3: Update Your Template
Fix the Power Select's searchField (it should target the display label of your options, not the array itself) and use the sorted array for your table:
{{!-- app/templates/servicerequests/index.hbs --}} {{#power-select options=filterOptions placeholder="Select a filter" selected=selectedFilter onchange=(action (mut selectedFilter)) searchField="label" {{!-- This matches the label property in filterOptions --}} as |filter| }} {{filter.label}} {{/power-select}} {{!-- Optional: Add a toggle for sort direction (Octane only) --}} <button {{action (mut isAscending) (not isAscending)}}> Sort: {{if isAscending 'Ascending' 'Descending'}} </button> <table> <thead> <tr> <th>Request ID</th> <th>Status</th> <th>Created Date</th> <!-- Add other table headers --> </tr> </thead> <tbody> {{#each sortedServiceRequests as |request|}} <tr> <td>{{request.id}}</td> <td>{{request.status}}</td> <td>{{request.createdAt}}</td> <!-- Add other table cells --> </tr> {{/each}} </tbody> </table>
Key Notes
- Filter Option Structure: Make sure
filterOptionsincludes alabel(for display) andvalue(matching the field name on yourservicerequestmodel). - Reactivity: By moving sorting to the controller, changes to
selectedFilter(orisAscending) will automatically trigger a re-sort and update the table. - Performance: If you have a large dataset, consider using Ember's
arrayProxyor pagination to keep sorting fast.
内容的提问来源于stack exchange,提问作者spacerobot

