Skip to content

Commit af8fd6d

Browse files
JerryWu1234wuls
andauthored
fix: input's value is string when passing number on V1 (#7249)
* fix: a bug related to 7182, migrate the code --------- Co-authored-by: wuls <[email protected]>
1 parent c17298d commit af8fd6d

File tree

7 files changed

+96
-14
lines changed

7 files changed

+96
-14
lines changed

.changeset/witty-radios-pump.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@builder.io/qwik': patch
3+
---
4+
5+
fix: input's value is string when passing number

packages/docs/src/routes/docs/(qwik)/components/rendering/index.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,17 @@ The `bind:` is compiled away by the Qwik optimizer to a property set and an even
180180
import { component$, useSignal } from '@builder.io/qwik';
181181

182182
export default component$(() => {
183+
const count = useSignal(0);
183184
const firstName = useSignal('');
184185
const acceptConditions = useSignal(false);
185186

186187
return (
187188
<form>
189+
{/* For number inputs, use `valueAsNumber` instead of `value` to get the numeric value directly */}
190+
<input type="number"
191+
value={count.value}
192+
onInput$={(_, el) => count.value = el.valueAsNumber }
193+
/>
188194
<input type="text"
189195
value={firstName.value}
190196
onInput$={(_, el) => firstName.value = el.value }

packages/qwik/src/core/render/jsx/types/jsx-generated.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ type SpecialAttrs = {
596596
* For type: HTMLInputTypeAttribute, excluding 'button' | 'reset' | 'submit' | 'checkbox' |
597597
* 'radio'
598598
*/
599-
'bind:value'?: Signal<string | undefined>;
599+
'bind:value'?: Signal<string | undefined | number>;
600600
enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send' | undefined;
601601
height?: Size | undefined;
602602
max?: number | string | undefined;

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__example_input_bind.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const Greeter = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(()=>{
4444
"value": value,
4545
"onInput$": /*#__PURE__*/ inlinedQrl((_, elm)=>{
4646
const [value] = useLexicalScope();
47-
return value.value = elm.value;
47+
return value.value = elm.type == "number" ? elm.valueAsNumber : elm.value;
4848
}, "s_6IZeYpXCNXA", [
4949
value
5050
])
@@ -53,7 +53,7 @@ export const Greeter = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(()=>{
5353
"checked": checked,
5454
"onInput$": /*#__PURE__*/ inlinedQrl((_, elm)=>{
5555
const [checked] = useLexicalScope();
56-
return checked.value = elm.checked;
56+
return checked.value = elm.type == "number" ? elm.valueAsNumber : elm.checked;
5757
}, "s_JPI3bLCVnso", [
5858
checked
5959
])
@@ -62,7 +62,7 @@ export const Greeter = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(()=>{
6262
"stuff": stuff,
6363
"onChange$": /*#__PURE__*/ inlinedQrl((_, elm)=>{
6464
const [stuff] = useLexicalScope();
65-
return stuff.value = elm.stuff;
65+
return stuff.value = elm.type == "number" ? elm.valueAsNumber : elm.stuff;
6666
}, "s_eyREJ0lZTFw", [
6767
stuff
6868
])

packages/qwik/src/optimizer/core/src/transform.rs

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,17 +1298,59 @@ impl<'a> QwikTransform<'a> {
12981298
),
12991299
),
13001300
op: ast::AssignOp::Assign,
1301-
right: Box::new(ast::Expr::Member(
1302-
ast::MemberExpr {
1303-
obj: Box::new(ast::Expr::Ident(elm)),
1304-
prop: ast::MemberProp::Ident(
1305-
ast::IdentName::new(
1306-
prop_name, DUMMY_SP,
1307-
),
1308-
),
1301+
right: Box::new(ast::Expr::Cond(ast::CondExpr {
1302+
test: Box::new(ast::Expr::Bin(ast::BinExpr {
1303+
left: Box::new(ast::Expr::Member(
1304+
ast::MemberExpr {
1305+
obj: Box::new(ast::Expr::Ident(
1306+
elm.clone(),
1307+
)),
1308+
prop: ast::MemberProp::Ident(
1309+
ast::IdentName::new(
1310+
"type".into(),
1311+
DUMMY_SP,
1312+
),
1313+
),
1314+
span: DUMMY_SP,
1315+
},
1316+
)),
13091317
span: DUMMY_SP,
1310-
},
1311-
)),
1318+
op: ast::BinaryOp::EqEq,
1319+
right: Box::new(ast::Expr::Lit(
1320+
ast::Lit::Str(ast::Str {
1321+
value: "number".into(),
1322+
span: DUMMY_SP,
1323+
raw: None,
1324+
}),
1325+
)),
1326+
})),
1327+
cons: Box::new(ast::Expr::Member(
1328+
ast::MemberExpr {
1329+
obj: Box::new(ast::Expr::Ident(
1330+
elm.clone(),
1331+
)),
1332+
prop: ast::MemberProp::Ident(
1333+
ast::IdentName::new(
1334+
"valueAsNumber".into(),
1335+
DUMMY_SP,
1336+
),
1337+
),
1338+
span: DUMMY_SP,
1339+
},
1340+
)),
1341+
alt: Box::new(ast::Expr::Member(
1342+
ast::MemberExpr {
1343+
obj: Box::new(ast::Expr::Ident(elm)),
1344+
prop: ast::MemberProp::Ident(
1345+
ast::IdentName::new(
1346+
prop_name, DUMMY_SP,
1347+
),
1348+
),
1349+
span: DUMMY_SP,
1350+
},
1351+
)),
1352+
span: DUMMY_SP,
1353+
})),
13121354
span: DUMMY_SP,
13131355
}),
13141356
))),
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { component$, useSignal } from "@builder.io/qwik";
2+
export default component$(() => {
3+
const a = useSignal(1);
4+
const b = useSignal(2);
5+
6+
return (
7+
<div>
8+
{a.value} + {b.value} = <span id="result">{a.value + b.value}</span>
9+
<input type="number" id="input1" bind:value={a} />
10+
<input type="number" id="input2" bind:value={b} />
11+
</div>
12+
);
13+
});

starters/e2e/qwikcity/nav.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,22 @@ test.describe("actions", () => {
432432
await expect(href).toHaveAttribute("href", site);
433433
});
434434

435+
test("issue7182", async ({ page, javaScriptEnabled }) => {
436+
await page.goto("/qwikcity-test/issue7182");
437+
const input1 = await page.locator("#input1");
438+
await input1.fill("4");
439+
await input1.dispatchEvent("change");
440+
const input2 = await page.locator("#input2");
441+
await input2.fill("4");
442+
await input2.dispatchEvent("change");
443+
const result = await page.locator("#result");
444+
if (javaScriptEnabled) {
445+
await expect(result).toHaveText("8");
446+
} else {
447+
await expect(result).toHaveText("3");
448+
}
449+
});
450+
435451
test("media in home page", async ({ page }) => {
436452
await page.goto("/qwikcity-test/");
437453

0 commit comments

Comments
 (0)