AngularJS Formly:表单渲染后动态切换字段类型实现编辑/展示模式
This is a super common use case, and there's a clean, straightforward way to implement it. Here's how I'd approach it:
Step 1: Create a custom "display" field type
First, define a reusable field type for your display mode that renders values as plain <span> elements. This keeps your display mode consistent across all fields, and you can even add formatting flexibility:
angular.module('yourApp', ['formly', 'formlyBootstrap']) .config(function(formlyConfigProvider) { // Custom display type for read-only mode formlyConfigProvider.setType({ name: 'display', template: '<span>{{model[options.key] | filter: options.templateOptions.displayFilter || "identity"}}</span>' }); });
The optional filter lets you format values (like dates or numbers) nicely when in display mode.
Step 2: Define fields with their edit types
In your controller, set up your fields with a dedicated editType property that specifies which input component to use in edit mode. This makes toggling between modes a breeze:
.controller('FormCtrl', function($scope) { // Toggle flag for edit/display mode $scope.isEditing = false; // Your form fields - define editType for each $scope.fields = [ { key: 'fullName', editType: 'input', templateOptions: { label: 'Full Name', type: 'text' } }, { key: 'userRole', editType: 'select', templateOptions: { label: 'Role', options: [ {value: 'admin', name: 'Administrator'}, {value: 'editor', name: 'Content Editor'}, {value: 'viewer', name: 'Viewer'} ] } }, { key: 'joinDate', editType: 'datetimepicker', // Assume you have this custom edit type set up templateOptions: { label: 'Join Date', displayFilter: 'date:"MM/dd/yyyy"' // Format date for display mode } }, { key: 'notifications', editType: 'checkbox', templateOptions: { label: 'Enable Notifications' } } ]; // Helper functions to switch modes const setDisplayMode = () => { $scope.fields.forEach(field => { field.type = 'display'; }); $scope.isEditing = false; }; const setEditMode = () => { $scope.fields.forEach(field => { field.type = field.editType; }); $scope.isEditing = true; }; // Toggle function triggered by your button $scope.toggleEditMode = () => { $scope.isEditing ? setDisplayMode() : setEditMode(); }; // Initialize form in display mode setDisplayMode(); // Your form model $scope.model = { fullName: 'Jane Smith', userRole: 'editor', joinDate: new Date('2023-01-15'), notifications: true }; });
Step 3: Add the toggle button and form in your template
Your HTML will be simple—just a button to switch modes and the Formly form itself:
<div ng-controller="FormCtrl"> <button class="btn btn-primary" ng-click="toggleEditMode()"> {{ isEditing ? 'Save & View' : 'Edit Form' }} </button> <div class="mt-3"> <formly-form model="model" fields="fields" form="formInstance"> </formly-form> </div> </div>
How this works
AngularJS Formly watches the fields array for changes. When you update the type property of each field, Formly automatically re-renders the field with the new component. Since all other field properties (like key, templateOptions.label, and layout-related settings) stay the same, your form layout will remain identical between edit and display modes.
Bonus tips
- For complex components like typeaheads, make sure your custom edit type is properly configured before switching to it.
- If you need to validate before switching from edit to display mode, add checks in the
toggleEditModefunction (e.g., check ifformInstance.$valid). - You can extend the
displaytype to handle empty values gracefully (e.g., show "N/A" ifmodel[options.key]is null).
内容的提问来源于stack exchange,提问作者DeJoT

