Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Answer:1 #778

Closed
wants to merge 8 commits into from
Closed

Answer:1 #778

wants to merge 8 commits into from

Conversation

chekit
Copy link

@chekit chekit commented Apr 16, 2024

Checklist for challenge submission

  • [x ] Start your PR message with Answer:${challenge_number}

Warning:

  • If you want feedback or review, you must support the project on GitHub:
    • $5 per review
    • $25 for lifetime reviews
    • Create one of more challenges
    • Have many valuable contributions to the project

Alternatively, you can still submit your PR to join the list of answered challenges or to be reviewed by a community member. 🔥

@tomalaforge tomalaforge added answer answer 1 exercice projection labels Apr 16, 2024
Copy link

@GregOnNet GregOnNet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @chekit,

thank you so much for your PR. 🙏🏻
This is the first review, I do.
So please do not take my comments too serious.

Here are general thoughts about the given goal “. The goal of the challenge is to create a CardComponent that can be customized without any modifications.”

  • I think the typing of the list-input of CardComponent would cause an issue, since the typing limits the usage to objects having id, firstname, name.
  • Other than that, I think the intention was to make the card reusable by using ngTemplateOutlet
  • Nevertheless, you managed to make the card reusable by abstracting the data-model.
  • In the end, I think ngTemplateOutlet makes the card more reusable.

Btw:
I am not sure if I should approve the PR or not.
Not sure about the process, here. :-) //cc @tomalaforge

Cheers from Leipzig, Germany
Gregor

template: 'TODO City',
template: `
<app-card
[list]="data$ | async"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool that you use a stream here.
You should be able to use ChangeDetectionStrategy.OnPush here.

#performance #no-blocker

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely make sense 👍🏻

template: `
<app-card
[list]="data$ | async"
(addNewItem)="onAddNewItem()"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of onAddNewItem you could be more specific about the handler → addNewCitiy().

#personalPerference #no-blocker

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, as you noticed later the intention was to move all repetitive code out of components, to make it possible to handle it in one place.

[list]="data$ | async"
(addNewItem)="onAddNewItem()"
(deleteItem)="onDeleteItem($event)"
[backgroundColor]="'rgba(250, 10, 250, 0.1)'">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is better than using ::ng-deep.

We could also think of allowing to pass a class-name: backgroundClass="bg-red-200"

This allows to reuse styles from an existing CSS-Framework like prime flex or tailwind.

#idea #no-blocker

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left it with style, but with refactored implementation class could be easily implemented as well :)


this.store.teachers$.subscribe((t) => (this.teachers = t));
override onAddNewItem() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, now I understand the “generic” naming.

From my experience, this adds another layer of indirection that does not provide a benefit for the developer.
This approach makes absolute sense to me if we are in the area of spinning up components dynamically from a configuration. Then we need to introduce contracts and hooks.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to move all repeated functionality to abstract class (DRY), thus you don't need to copy paste it once you create a new card type component and focus only on the things that differs this component from others.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to move all repeated functionality to abstract class (DRY), thus you don't need to copy paste it once you create a new card type component and focus only on the things that differs this component from others.

Yes, I understand the goal. As far as I can tell, this approach only works in very few situations.
Often we tend to abstract too early. Then a business requirement changes, and we start adding conditions to our abstractions in order to make them work for a specific case.

That's why I value SRP (Single Responsibility Principle) over DRY.
In our challenge here, I would ask, what is a card responsible for? Aha, providing a visual boundary and a spot to render
any content.

Add
</button>
</div>
`,
styles: `
.card__image {
width: 200px;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to hard-code the width of the image here, if our goal is to have an abstract card-implementation?

#api #no-blocker

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, put this back to the specific card as it was initially.

src="assets/img/student.webp"
width="200px" />

[bgColor]="backgroundColor()">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we allow passing a CSS-class, we do not need the custom BgColorDirective.

#no-blocker #less-code-to-maintain

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, now I see what you mean. It is definitely look like an overhead.

@Input() list: any[] | null = null;
@Input() type!: CardType;
@Input() customClass = '';
list = input<{ id: number; firstName?: string; name?: string }[] | null>(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This typing limits the data structure we can pass to the card.
How would we act if we would like to use this card for displaying a Product having no firstname.

Maybe it is possible to make CardComponent generic: CardComponent<T>

#api

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. With the ngTemplateOutlet approach it is not need to be too specific for list property.

@chekit
Copy link
Author

chekit commented Apr 19, 2024

Hi @chekit,

thank you so much for your PR. 🙏🏻 This is the first review, I do. So please do not take my comments too serious.

Here are general thoughts about the given goal “. The goal of the challenge is to create a CardComponent that can be customized without any modifications.”

  • I think the typing of the list-input of CardComponent would cause an issue, since the typing limits the usage to objects having id, firstname, name.
  • Other than that, I think the intention was to make the card reusable by using ngTemplateOutlet
  • Nevertheless, you managed to make the card reusable by abstracting the data-model.
  • In the end, I think ngTemplateOutlet makes the card more reusable.

Btw: I am not sure if I should approve the PR or not. Not sure about the process, here. :-) //cc @tomalaforge

Cheers from Leipzig, Germany Gregor

Hi @GregOnNet,

Thank you a lot for such a detailed review. It was really nice to practice and recall the concepts which I'm not using everyday. I did some changes and left a comments to your comments.

Once again, much appreciation :)

P.S.
I'm not sure you need to approve PR to not override the original exercise

Cheers from Amsterdam, The Netherlands. Anton 😉

@GregOnNet
Copy link

@chekit Hey, thanks for the feedback. I really appreciate it.

Yes, I learned, that these PRs are tagged in order to mark them as answer. :-)

Copy link

github-actions bot commented May 9, 2024

This pull request is stale because it has been open for 15 days with no activity.

@github-actions github-actions bot added the stale label May 9, 2024
Copy link

This pull request was closed because it has been inactive for 5 days since being marked as stale.

@github-actions github-actions bot closed this May 15, 2024
@tomalaforge tomalaforge removed the stale label May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1 exercice projection answer answer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants