Giter VIP home page Giter VIP logo

Comments (10)

alxhub avatar alxhub commented on June 19, 2024 2

I'm going to steal this issue and refocus it a bit. transform support isn't necessary to address the problem you're talking about. If we had a way to declare that model() will emit a narrower type than it accepts, then it could support two-way binding to a WritableSignal<number> since Signal<number> is assignable to Signal<number|string> and we'd never try to write a string back.

from angular.

alxhub avatar alxhub commented on June 19, 2024

This is a duplicate of #55166 which has the previous discussion (which concluded that model() should not support transform).

from angular.

Harpush avatar Harpush commented on June 19, 2024

I'm going to steal this issue and refocus it a bit. transform support isn't necessary to address the problem you're talking about. If we had a way to declare that model() will emit a narrower type than it accepts, then it could support two-way binding to a WritableSignal<number> since Signal<number> is assignable to Signal<number|string> and we'd never try to write a string back.

But how would you transform the string to the number for input values? At the end the component internally only want number and will always emit number. Only the outside can provide strings.

from angular.

alxhub avatar alxhub commented on June 19, 2024

But how would you transform the string to the number for input values? At the end the component internally only want number and will always emit number. Only the outside can provide strings.

You can use a computed to go from number|string to just number.

from angular.

Harpush avatar Harpush commented on June 19, 2024

But how would you transform the string to the number for input values? At the end the component internally only want number and will always emit number. Only the outside can provide strings.

You can use a computed to go from number|string to just number.

But wouldn't something like model(2, {inputTansform: fn}) makes more sense? Especially if we look at it as input and output - a model built from input with transform and output with actual type. The output type must be assigned to the input type.

from angular.

Harpush avatar Harpush commented on June 19, 2024

@alxhub Just adding that using input and output we can do:

value = input(2, { transform: fn });
valueChange = output<number>();

The only downside is we can't change it from inside and the outside must implement the output and input or two way binding.
Hence the suggested:

value = model(2, {inputTansform: fn});

Which does exactly the same but with model added features.

from angular.

alxhub avatar alxhub commented on June 19, 2024

After some discussion, we've decided that it's not really feasible to implement this feature.

One, we (still) don't want to add transform to model. The intention of the model input is that it offers synchronization between the parent component and the model, and that synchronization breaks if a one-way transformation is introduced. This could be interrupted

Narrowing the setter type wouldn't work, as it would break the assignability of model inputs to the WritableSignal interface which has no such restrictions.

Given that both options produce tradeoffs that we don't feel strike the right balance, we don't think a change here makes sense.

from angular.

Harpush avatar Harpush commented on June 19, 2024

@alxhub so how do you suggest to implement it instead? Using input and output requires the consumer to use two way binding for it to work (btw isn't it the same as what was suggested here but without internal control?)

from angular.

alxhub avatar alxhub commented on June 19, 2024

Falling back to input & output is I think is a good workaround.

// Input with transform: signal of the internal value.
state = input(..., {transform: ...}); // InputSignal<Wide, Narrow>

// Output side of the two-way binding contract.
stateChange = output<Narrow>();

// Computed to project new input values to a WritableSignal, allowing internal mutations.
stateMutable = computed(() => signal(this.state())); // Signal<WritableSignal<Narrow>>;

// Actual value to use internally (unwrap the nested WritableSignal).
stateInternal = computed(() => this.stateMutable()()); // Signal<Narrow>

// Helper method to update the state (equivalent of `model.set()`).
setState(value: Narrow): void {
  this.stateMutable().set(value);
  this.stateChange(value);
}

from angular.

Harpush avatar Harpush commented on June 19, 2024

Falling back to input & output is I think is a good workaround.

// Input with transform: signal of the internal value.
state = input(..., {transform: ...}); // InputSignal<Wide, Narrow>

// Output side of the two-way binding contract.
stateChange = output<Narrow>();

// Computed to project new input values to a WritableSignal, allowing internal mutations.
stateMutable = computed(() => signal(this.state())); // Signal<WritableSignal<Narrow>>;

// Actual value to use internally (unwrap the nested WritableSignal).
stateInternal = computed(() => this.stateMutable()()); // Signal<Narrow>

// Helper method to update the state (equivalent of `model.set()`).
setState(value: Narrow): void {
  this.stateMutable().set(value);
  this.stateChange(value);
}

Thanks that's helpful! Just a shame that such a pattern can't be integrated in angular for easier implementation. Especially if there are multiple of those inputs. Models are such a clean way to do it.
I guess one can create a wrapper so it ends up with: input,output,internal wrapper

from angular.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.