{"record":{"id":"e16c093354e6ae54","repo":"tailwindlabs/headlessui","slug":"passing-props-on-template-the-current-componen","errorCode":null,"errorMessage":"Passing props on \"template\"!\n\nThe current component <${name} /> is rendering a \"template\".\nHowever we need to passthrough the following props:\n  - ${line}\n\nYou can apply a few solutions:\n  - Add an `as=\"...\"` prop, to ensure that we render an actual element instead of a \"template\".\n  - Render a single element as the child so that we can forward the props onto that element.","messagePattern":"Passing props on \"template\"!\n\nThe current component <(.+?) /> is rendering a \"template\"\\.\nHowever we need to passthrough the following props:\n  - (.+?)\n\nYou can apply a few solutions:\n  - Add an `as=\"\\.\\.\\.\"` prop, to ensure that we render an actual element instead of a \"template\"\\.\n  - Render a single element as the child so that we can forward the props onto that element\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@headlessui-vue/src/utils/render.ts","lineNumber":117,"sourceCode":"      if (typeof v === 'boolean') {\n        exposeState = true\n      }\n      if (v === true) {\n        states.push(k)\n      }\n    }\n\n    if (exposeState) dataAttributes[`data-headlessui-state`] = states.join(' ')\n  }\n\n  if (as === 'template') {\n    children = flattenFragments(children ?? [])\n\n    if (Object.keys(incomingProps).length > 0 || Object.keys(attrs).length > 0) {\n      let [firstChild, ...other] = children ?? []\n\n      if (!isValidElement(firstChild) || other.length > 0) {\n        throw new Error(\n          [\n            'Passing props on \"template\"!',\n            '',\n            `The current component <${name} /> is rendering a \"template\".`,\n            `However we need to passthrough the following props:`,\n            Object.keys(incomingProps)\n              .concat(Object.keys(attrs))\n              .map((name) => name.trim())\n              .filter((current, idx, all) => all.indexOf(current) === idx)\n              .sort((a, z) => a.localeCompare(z))\n              .map((line) => `  - ${line}`)\n              .join('\\n'),\n            '',\n            'You can apply a few solutions:',\n            [\n              'Add an `as=\"...\"` prop, to ensure that we render an actual element instead of a \"template\".',\n              'Render a single element as the child so that we can forward the props onto that element.',\n            ]","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/tailwindlabs/headlessui/blob/eea57cf46fd6767ed1059012f7073b88eb159fba/packages/@headlessui-vue/src/utils/render.ts#L99-L135","documentation":"When a Headless UI Vue component renders with `as=\"template\"`, it must forward its props onto a single valid child element. `_render` throws when there are incoming props/attrs to passthrough but the children are not exactly one valid element (no children, multiple children, or text/fragment roots), because there is no unambiguous place to put the props.","triggerScenarios":"Using `as=\"template\"` with zero children, multiple children, or a text node as the child while the component has props to forward (id, class, aria-*, data-* attributes, event listeners).","commonSituations":"`<DialogOverlay as=\"template\">` wrapping multiple elements; `<PopoverButton as=\"template\"><MyCustomButton/></PopoverButton>` where the child is a component fragment; passing extra attrs to a template-rendered component whose slot content is empty or a plain string.","solutions":["Render exactly one real element as the sole child of the template-rendered component: `<PopoverButton as=\"template\"><button>...</button></PopoverButton>`.","Or drop `as=\"template\"` and set `as=\"div\"` (or the desired tag) so the component renders its own element and attaches props itself.","Remove extra passthrough props/listeners if you intended a fragment render (not recommended; you lose a11y attrs)."],"exampleFix":"<!-- before -->\n<PopoverButton as=\"template\">\n  <span>More</span> <Icon icon=\"chevron\" />\n</PopoverButton>\n\n<!-- after -->\n<PopoverButton as=\"template\">\n  <button>More <Icon icon=\"chevron\" /></button>\n</PopoverButton>","handlingStrategy":"validation","validationCode":"// Ensure the as=\"template\" component has exactly one element child before rendering\n// e.g. structure: <Comp as=\"template\"><div>...</div></Comp>","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always give template-rendered components exactly one element child.","Prefer as=\"div\" when unsure.","Keep custom child components single-rooted so attrs can be forwarded."],"tags":["headlessui","vue","template","props-passthrough","render"],"backgroundTag":"multiple-root-nodes-in-vue","analyzedSha":"eea57cf46fd6767ed1059012f7073b88eb159fba","analyzedAt":"2026-08-28T19:22:46.163Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}