@homebound/form-state 2.2.8 → 2.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/formState.js CHANGED
@@ -314,11 +314,8 @@ function newValueFieldState(parentInstance, parentState, key, rules, isIdKey, is
314
314
  },
315
315
  blur() {
316
316
  // Now that the user is done editing the field, we sneak in some trim logic
317
- if (typeof this.value === "string") {
318
- this.set(this.value.trim());
319
- if (this.value === "") {
320
- this.set(undefined);
321
- }
317
+ if (this._focused) {
318
+ this.maybeTrim();
322
319
  }
323
320
  this._focused = false;
324
321
  // touched is readonly, but we're allowed to change it
@@ -351,6 +348,11 @@ function newValueFieldState(parentInstance, parentState, key, rules, isIdKey, is
351
348
  if (opts.refreshing) {
352
349
  this.originalValue = newValue;
353
350
  }
351
+ // If we're being set programmatically, i.e. we don't currently have focus,
352
+ // call blur to trigger any auto-saves.
353
+ if (!this._focused) {
354
+ this.blur();
355
+ }
354
356
  },
355
357
  reset() {
356
358
  if (!computed) {
@@ -375,6 +377,17 @@ function newValueFieldState(parentInstance, parentState, key, rules, isIdKey, is
375
377
  _originalValue = v;
376
378
  _originalValueTick.value++;
377
379
  },
380
+ maybeTrim() {
381
+ if (typeof this.value === "string") {
382
+ let newValue = this.value.trim();
383
+ if (newValue === "") {
384
+ newValue = undefined;
385
+ }
386
+ if (newValue !== this.value) {
387
+ this.set(newValue);
388
+ }
389
+ }
390
+ },
378
391
  };
379
392
  return field;
380
393
  }
@@ -556,7 +569,10 @@ function newListFieldState(parentInstance, parentState, key, rules, listConfig,
556
569
  _tick.value++;
557
570
  },
558
571
  };
559
- return list;
572
+ return mobx_1.makeAutoObservable(list, {
573
+ // See other makeAutoObservable comment
574
+ value: mobx_1.computed({ equals: () => false }),
575
+ });
560
576
  }
561
577
  function isNotUndefined(value) {
562
578
  return value !== undefined;
@@ -117,6 +117,19 @@ describe("formState", () => {
117
117
  expect(state.books.rows[2].originalValue === b1).toEqual(true);
118
118
  expect(ticks).toEqual(3);
119
119
  });
120
+ it("list value can observe changes", () => {
121
+ const b1 = { title: "t1" };
122
+ const a1 = { firstName: "a1", books: [b1] };
123
+ const state = createAuthorInputState(a1);
124
+ let books;
125
+ let ticks = 0;
126
+ mobx_1.autorun(() => {
127
+ books = state.books.value;
128
+ ticks++;
129
+ });
130
+ state.books.add({ title: "t2" }, 0);
131
+ expect(ticks).toEqual(2);
132
+ });
120
133
  it("maintains unknown fields", () => {
121
134
  // Given the form is not directly editing id fields
122
135
  const config = {
@@ -321,7 +334,7 @@ describe("formState", () => {
321
334
  a1.books.remove(0);
322
335
  expect(a1.dirty).toBeFalsy();
323
336
  });
324
- it("it calls onBlur when adding or removing to a list", () => {
337
+ it("calls onBlur when adding or removing to a list", () => {
325
338
  const onBlur = jest.fn();
326
339
  const a1 = createAuthorInputState({ books: [] }, onBlur);
327
340
  expect(a1.books.dirty).toBeFalsy();
@@ -331,6 +344,26 @@ describe("formState", () => {
331
344
  expect(a1.dirty).toBeFalsy();
332
345
  expect(onBlur).toBeCalledTimes(2);
333
346
  });
347
+ it("calls onBlur when programmatically setting a value", () => {
348
+ const onBlur = jest.fn();
349
+ // Given an author listening for blur
350
+ const a1 = createAuthorInputState({ books: [{}] }, onBlur);
351
+ // When we programmatically set a field that isn't focused
352
+ a1.firstName.value = "first";
353
+ // Then we call onBlur
354
+ expect(onBlur).toBeCalledTimes(1);
355
+ });
356
+ it("defers calling onBlur when setting a bound value", () => {
357
+ const onBlur = jest.fn();
358
+ // Given an author listening for blur
359
+ const a1 = createAuthorInputState({ books: [{}] }, onBlur);
360
+ // And the field is focused
361
+ a1.firstName.focus();
362
+ // When we we set the field
363
+ a1.firstName.value = "first";
364
+ // Then we don't call onBlur
365
+ expect(onBlur).toBeCalledTimes(0);
366
+ });
334
367
  it("knows list of primitives are dirty", () => {
335
368
  const a1 = formState_1.createObjectState({ favoriteColors: { type: "value" } }, {});
336
369
  expect(a1.favoriteColors.dirty).toBeFalsy();
@@ -951,6 +984,7 @@ describe("formState", () => {
951
984
  it("trims string values on blur", () => {
952
985
  const formState = formState_1.createObjectState(authorWithBooksConfig, { firstName: "f", lastName: "l" });
953
986
  // Given the user is typing with spaces
987
+ formState.firstName.focus();
954
988
  formState.firstName.set("f ");
955
989
  // And we initially keep the space
956
990
  expect(formState.firstName.value).toEqual("f ");
@@ -962,6 +996,7 @@ describe("formState", () => {
962
996
  it("trims empty values to undefined on blur", () => {
963
997
  const formState = formState_1.createObjectState(authorWithBooksConfig, { firstName: "f", lastName: "l" });
964
998
  // Given the user is typing with only spaces
999
+ formState.firstName.focus();
965
1000
  formState.firstName.set(" ");
966
1001
  // And we initially keep the space
967
1002
  expect(formState.firstName.value).toEqual(" ");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/form-state",
3
- "version": "2.2.8",
3
+ "version": "2.2.9",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",