Skip to content

overridable: add dynamicParametrize function #300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/lib/utils/fieldComponents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// This file is part of React-Invenio-Forms
// Copyright (C) 2025 CERN.
//
// React-Invenio-Forms is free software; you can redistribute it and/or modify it
// under the terms of the MIT License; see LICENSE file for more details.

import { useFormikContext } from "formik";
import * as React from "react";

/**
* Override the parameters of a component (similarly to `parametrize`) using certain available
* context variables.
*
* Currently, the following arguments are passed into the `propsFactory` function:
* - `existingProps`: the props originally passed into the component before the override
* - `formValues`: an object of the values in the Formik form state
*
* The `propsFactory` function should return an object of the props to be used for overriding the
* specified `Component`
*
* This function is adapted from `react-overridable`: https://github.com/indico/react-overridable/blob/d1ecfbec9993a461717824259900eec82d59f1e0/src/overridable.js#L7-L33
*
* @param Component - the React component to override the parameters, as in `parametrize` from react-overridable.
* @param {function} propsFactory - function returning the props to override the component with
*/
export function dynamicParametrize(Component, propsFactory) {
const ParametrizedComponent = (props) => {
const { values } = useFormikContext();
const extraProps = propsFactory({ existingProps: props, formValues: values });

// Store the original component in an attribute
if (Component.originalComponent) {
Component = Component.originalComponent;
}

// overrideProps override props if there is a name collision
const { children, ...attrProps } = { ...props, ...extraProps };
return React.createElement(Component, attrProps, children);
};

const name = Component.displayName || Component.name;
ParametrizedComponent.displayName = `Parametrized(${name})`;
return ParametrizedComponent;
}
1 change: 1 addition & 0 deletions src/lib/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { humanReadableBytes } from "./humanReadableBytes";
export { dropdownOptionsGenerator } from "./dropdownOptionsGenerator";
export { dynamicParametrize } from "./fieldComponents";