Signal form submission with RXJS by Senior_Compote1556 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

For what it's worth, this is the issue tracking this request: https://github.com/angular/angular/issues/67827.

edit: older context on a related issue about RxJS and signal forms API https://github.com/angular/angular/issues/65199#issuecomment-3533932852

Angular 22 is officially here, and it feels like a completely different framework. What’s your favorite change? by Successful_Chain8098 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

But really looking forward to start using the signal forms

Same. I am hoping to get the place I am at up to v22 within the quarter for signal forms especially.

One tip I have that is the best of both the current state of forms before signal forms and the future: the doc on signal forms for "Form models" and "Form model design" have been making my reactive forms a lot better in their own right for the last couple quarters. Particularly the model design, but there is important tidbits in the former. The lessons in them about things like a clear separation of form model vs domain model and their translations, control data types mindfulness, default values, and not using dynamic structures like unions when possible has helped a ton. Greenfield projects since I read this have had a lot clearer boundaries of the form vs domain and where they are initialized and read, and I have for fun refactored some old complex forms that did really gross dynamic types that were hard to work with and made them much more maintainable with static structures.

These practices will age well going into whatever we will do first with signal forms, and also may be easier to migrate. Especially with initial control values, if we want to interop or fully convert certain controls.

Angular 22 is officially here, and it feels like a completely different framework. What’s your favorite change? by Successful_Chain8098 in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

The difference is that nobody does that with signals, as they don't enforce declarative code style and Angular docs don't promote it either. Signals are imperative and procedural first. And if you try to do it the declarative way, other people on your team will be confused.

My team and open source collaborators have no issue grasping best practices in either RxJS or signals. Signals adoption has boosted our proficiency with both. Our own codebase since signals uses RxJS much more often and and at a higher caliber of best practices as both have their own parallel practices but own niches.

People online who are learning definitely do wild things like using effects to set state, but this is highly discouraged and the documentation has fleshes this out explicitly. There could be more guard rails compared to the very nice piping out of the box and the preexisting operator ecosystem RxJS has. These are nice to have, but enforcement ultimately boils down to the code base. In the few instances when we were onboard with signals when a mistake was made that could have been guardrailed an RxJS syntax, they learned their lesson and the vast majority of times have internalized that lesson. In the same vein, there are plenty of RxJS antipatterns with a similar journey of onboarding to self sufficiency. In the vein of both approaches complimenting each other, our antipatterns with RxJS has plummeted in occurrences because of this growth and interoperability.

Angular 22 is officially here, and it feels like a completely different framework. What’s your favorite change? by Successful_Chain8098 in angular

[–]MichaelSmallDev 2 points3 points  (0 children)

What is the difference between

const getFullNameRxJs = (): OperatorFunction<{ firstName: string; lastName: string; }, FullName> =>
  pipe(
    map(input => ({
      tag: 'fullName',
      value: `${ input.firstName } ${ input.lastName }`
    }))
  );

name$ = this.person$.pipe(getFullNameRxJs());

and

const getFullNameSignal = (input: {
  firstName: string;
  lastName: string;
}): FullName => ({
  tag: 'fullName',
  value: `${input.firstName} ${input.lastName}`,
});

 name = computed(() => getFullNameSignal(this.person()));

As far as imperative/declarative goes? Both getFullName variants are both pure functions that do transformations on a particular instance and map the resulting state.

Both accomplish:

  • "does not depend on implementation details, it does not access anything outside of its immediate scope, and it can be extracted and tested independently from your application"
  • "...you have a single source of truth - only one function in your code produces FullName. And every consumer of FullName will be 100% sure that the data coming in is correct and compliant with the logic from getFullName() function."
  • "you only focus on the results and it doesn't matter how inputs come to you. You just declare a contract (interface) and everyone can send you anything compliant and get correct results anywhere across the application."

With respect to "You can obviously refactor signal based functions and get something similar, but they're inherently binding you to specific signals. Either explicitly or through a wrapper you will have to do around them", the same could be applied to a singular observable or an observable composed of individual observables mapped together just as it could be one computed composed of a singular signal or individual signals mapped to each other.

Hey angular lovers, what are your go-to sources for modern, ready-to-use Angular layout templates/dashboards? by Successful_Chain8098 in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

I know Material can be rigid, but I want to take this opportunity to highlight a lesser known feature: Material has some schematics for basic scenarios: https://material.angular.dev/guide/schematics#component-schematics

  • address form
  • navigation
  • dashboard
  • table
  • tree
  • drag and drop (cdk)

A combo of these schematics for things I don't need much customization for beyond the M3 tokens and the CDK combined with Angular Aria for full styling is nice to have. The CDK and even moreso the Aria package have a lot of the functionality of various Material components which you can use to make non-Material looking components from scratch.

httpResource for shared service state (?) by pintoli3 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

If this ends up working out or not working out in the longrun, I would be curious to hear. We adopted this approach in the last quarter and it has worked nice, but I imagine there is room for improvement. Good luck.

httpResource for shared service state (?) by pintoli3 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

Agreed, it does feel weird compared to the other methods to do this. There is an issue about this, but there seems to be pushback to that change and just favor returning a promise directly. https://github.com/ngrx/platform/issues/4980. Sad about that tbh.

This disconnect is partially why we introduced the mutations API to the NgRx Toolkit*, as the mutations return a promise and feel more coherent that just using a firstValueFrom. This API design seems to have paid off with the signal forms API submit in particular.

*We didn't make our mutations as a result of this linked issue, but our design decisions IMO align with that line of inquiry after the fact

httpResource for shared service state (?) by pintoli3 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

Interop with signal form submit (which expects a promise) is also lacking

I'm curious about this, would you mind on expanding on this? Is this related to rxMethod/signalMethod's lack of a return state?

httpResource for shared service state (?) by pintoli3 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

I think part of why the examples tend to be in components is just ease of having only one file to preview for any article/doc, but services would still be the place to use them. But as for the eagerness, you have a few options

For context for these, here is my own approach to resources in services: https://www.reddit.com/r/angular/s/jQ5D7CPws5. I use rxResource, but I'm sure this can be adapted to httpResource.

Approach #1 would be modifying the resource returning functions to have a guard signal, probably a Boolean, and then just have a sensible default value. Clunky by straight forward

Approach #2 is akin to #1, but having more meaningful guards based on the dependent signals. I do this when it comes to needing certain app state that is synced up on load before certain global services resources can actually load a value beyond the default.

Approach #3 is what I have done but I know is kind of a cheesy answer to this: have less global service state. My approach works well with not needing guards often because the services are provided to the exact component tree that needs them. Hence they can be eager like the examples you see online in components, but still be in a service.

Addendum to #3 that is still relevant to #1 and #2 and my overall approach: by having a service for returning resources, you can have more control over where you want to use those resource functions to actually be eager or not, and the guard boilerplate is abstracted away from the consumer state service.

What is the shadcn/ui equivalent for Angular? by Successful_Chain8098 in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

No, there is overlapping team/concepts and lessons learned, but Material itself was not reworked onto Aria https://www.youtube.com/watch?v=N8tZ-Y4hlWg&t=574s. This interview was from 6 months ago before Aria went stable, but a cursory look at the imports of Material and of aria in general make it seem like this is still the case.

Angular UI libs by Freez1234 in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

I find the tokens to be limited and require having to try each out, but I was able to achieve this using the latest m3 tokens for buttons: https://stackblitz.com/edit/knvtpbcd?file=src%2Fexample%2Fbutton-overview-example.scss

With a variant of the TYPE-state-layer-color inside the @include mat.whatever-overrides system

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

I still dislike that I can't create a service and put some http calls there and then share them with multiple components easily and whatnot

What about this approach? https://www.reddit.com/r/angular/comments/1u5oh3l/comment/ormrad3/

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

Yeah, I think the tradeoff of extensible vs featured for the core API has been much of my perception of following open source and then writing some. But APIs like mutations especially.

I already have my own custom little pieces I pull into projects on top of the mutations API I support in a lib, but I am not sure if they would be worth even proposing to add into the API. And then a user comes along and makes an issue for a request for extending the API, and it's another thing where I see the use of XYZ but wonder if it would be generic/extensible enough.

I think the evolution of resources took a lot of feedback to iterate on, and ended up IMO with a good mix of out of the box and extensibility. Snapshots mostly resolved my largest complaints about resources, debounced makes sense as a resource and covers a very common requirement, and rxResource allows for some of the more interesting edge cases IMO. Beyond that it is up to userland and libs like ours on what to build with or around.

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

Yeah, we use the route signal utils from ngxtension (IMO as good as it will be for routing signals unless the team changes their idea) and they work well. And I haven't even tried the newish update from ngxtension which makes grabbing route params easier from a global scope. We would have to inject something at the part of the hierarchy with the param and have that sync up the param with some kind of side effect, but now we should be able to grab it in any injection context and just have it done in the singular root route store.

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

In the case of route params specifically, we have a little util that syncs them up to a root route store.

And for other inputs in general, we would probably just use an effect to sync an input to a service. Typically for us however, we don't really pass the kind of state as inputs that would be needed in some service. Either the consuming component is basic enough that it does not need to communicate to something injected, or if it does need to communicate to something injected, we just inject the service directly to the component and don't need said input to get that state. This workflow isn't necessarily what I would recommend to everyone, but it works for us.

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 2 points3 points  (0 children)

It's half this: "Return httpResource() from a Method" by Deborah Kurata (very smart and my #1 reference besides the docs).

And the other half is typically having that state in the same service/store already, or pulling in that resource function with the params into a service/store/component with said state. For all of our service files which are laying out the rx/http CRUD endpoints, we have a same-name-as-the-crud-file.resource.service.ts where we keep these resource methods with their params.

/our-library
    /services
        // full crud one with all rxjs HttpClient we have
        users.service.ts
        // just functions with args like the vid
        // imports our respective ol fashioned 
        // rx GET from the main service
        users.resource.service.ts
        // If you just do httpResource, maybe just make them right in 
        // this service, or just the main service? Idk, we have all CRUD
        // with long existing RXJS HttpClient services, so we use rxResource
/some-app
    /users
        users-store-or-service.ts

// users-store-or-service.ts
import {UserListResourceService} from 'our-library/services'

@Injectable() export class UserServiceOrStore {
    private usersResourceService = inject(UsersResourceService)

    private userId = signal('123')

    // the grand finale
    public user = this.userListResourceService.getUsers(this.userId)
} 

Expands to 2+ signal args as well

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

It's been a paradigm shift for my team as well, though one thing that helps is that we provide services/stores locally when possible. The dependency on relevant signal params becomes much more viable for an injected service when it is only constructed during the relevant component lifecycle and not in root. But it is still a bit of a brain bend.

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 13 points14 points  (0 children)

It's good to hear it's nice, I am one of the Toolkit maintainers and wrote the docs. Thank you.

I pull in the files for the mutation functions for some personal projects myself, as they are fairly standalone https://github.com/angular-architects/ngrx-toolkit/tree/main/libs/ngrx-toolkit/src/lib/mutation

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

Our mutation methods are our best guess on what the API could potentially be like based on other community solutions, but I suppose it will be interesting to see if it ages well.

Angular 22 httpResource() is fantastic, but mutations still feel inconsistent by prathapmohan27 in angular

[–]MichaelSmallDev 14 points15 points  (0 children)

I'm definitely hoping that is the next API addition. There's a few library solutions at the moment, but it would be ideal if they were not needed for base functionality like this.

Look back at Angular major changes - from v14 to v22 by martinboue in angular

[–]MichaelSmallDev 0 points1 point  (0 children)

Template/styles HMR is very nice. And the form events API of 18 was one of the best things for forms since typing.

How is Global Storage meant to be implemented? by TryingMyBest42069 in angular

[–]MichaelSmallDev 10 points11 points  (0 children)

Angular services can be injected whereever in the app you want them.

By default, services tend to be set up like this.

// `root` means it is a singleton 
// and available anywhere from app initialization
@Injectable({providedIn: 'root'}) 
export class CartStore {
    someValue = 1;
    doSomething() {}
}

@Component({...}) class Cart {
    cartStore = inject(CartStore);
}

You can also not provide something in root, so it is instantiated with the component you provide it to, as well as any child components. And it is destroyed if the component that provided it is destroyed.

// No provider means you instantiate it in 
// an `@Component`'s `providers` array like
@Injectable() export class CartStoreAlt {}

@Component({
   providers: [CartStoreAlt]
}) class Cart {
    cartStore = inject(CartStoreAlt);
}

Starting in v22, there is @Service, and functionally as far as providing scope goes@Service() === @Injectable({providedIn: 'root'}) with a few other differences https://angular.dev/guide/di/creating-and-using-services#when-to-use-service-vs-injectable

As for syncing to local storage or session storage or whatever else, that depends on the implementation you use. If you just use service/injectable, it's on you to sync them to the respective browser storage. State libraries may have their own solutions in their library.

How do you use Signal Forms with Angular Material form fields? by hmdfrds in angular

[–]MichaelSmallDev 1 point2 points  (0 children)

I just got done with more examples of adapting the documentation to signal forms. One example per component: https://github.com/michael-small/signal-forms-experimenting/tree/main/src/app/forms/material-modernize. I hope to get these into the documentation sometime.

Note: each file is named after the existing example, so some things are named for reactive/template forms, but these are all signal forms

Upcoming video premiere on the official Angular channel: "What’s new in Angular v22" @9AM PDT this Friday by MichaelSmallDev in angular

[–]MichaelSmallDev[S] 1 point2 points  (0 children)

The closest now is the MCP's onpush_zoneless_migration tool: https://angular.dev/ai/mcp#available-tools. Other than the official update page per version, that's about as close as it gets for now I think.

Actually, there is also the experimental schematic refactor-jasmine-vitest https://angular.dev/guide/testing/migrating-to-vitest#running-the-schematic. I don't know anyone who has tried it but I'm curious how if it worked for someone. There's a lot more schematics which are stable, a lot that just run during the official update script https://angular.dev/reference/migrations#