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

feat(ivy): implement some of the ViewContainerRef API #23189

Closed
wants to merge 1 commit into from

Conversation

marclaval
Copy link
Contributor

This PR implements some of the API of the ViewContainerRef and adds more tests.

In scope:

  • createEmbeddedView
  • insert
  • detach
  • length
  • get
  • indexOf
  • move

Out of scope:

  • createComponent
  • remove & clear (destroy part needs to be implemented)

@marclaval marclaval added action: review The PR is still awaiting reviews from at least one requested reviewer comp: ivy and removed cla: yes labels Apr 5, 2018
@googlebot
Copy link

☹️ Sorry, but only Googlers may change the label cla: yes.

@marclaval marclaval added the target: major This PR is targeted for the next major release label Apr 5, 2018
@@ -628,22 +628,29 @@ class ViewContainerRef implements viewEngine_ViewContainerRef {
return viewRef;
}
move(viewRef: viewEngine_ViewRef, currentIndex: number): viewEngine_ViewRef {

Choose a reason for hiding this comment

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

I know that you are not changing this part but the currentIndex is probably not the best arg name here. How about newIndex?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

currentIndex is the name of the arg in the ViewContainerRef abstract class. It makes some sense to keep it here, but it could be changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed it btw

this.detach(index);
// TODO(ml): proper destroy of the ViewRef
}
detach(index?: number|undefined): viewEngine_ViewRef|null {

Choose a reason for hiding this comment

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

it is enough to have index?: number (.? adds 'undefined')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

directiveInstance !.vcref.createEmbeddedView(directiveInstance !.tplRef, {name: s}, index);
}

function createTemplate() {

Choose a reason for hiding this comment

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

Could you please add code for a template in a comment of this function? It makes it easier to understand what is going on.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

elementEnd();
}

function updateTemplate() {

Choose a reason for hiding this comment

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

nit: isn't it too fragile as an utility function with the indexes hard-coded? Maybe you should pass container / element index as arguments to this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not needed yet, let's keep it simple until it is.

}

describe('createEmbeddedView (incl. insert)', () => {
it('should work on elements', () => {

Choose a reason for hiding this comment

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

How is this test different as compared to the existing one here:

it('should add embedded view into a view container on elements', () => {

Seems like both tests are trying to assert the same thing? Maybe we should merge it into one instead of having 2 similar ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed the old ones as the new ones are testing more cases with more concise code (except remove and clear, but it will be done later in another PR).

expect(() => { createView('Z', 5); }).toThrow();
});

it('should work on containers', () => {

Choose a reason for hiding this comment

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

As above we've got a similar test already:

it('should add embedded view into a view container on ng-template', () => {

Moreover I believe that we can't have a LContainerNode that is both:

  • created from a JS block
  • having a directive on it
    as it would require sth like:
% if (exp) { //how to add a directive here???
...
% }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See my comment above about refactoring.

About this test, it is true that this precise set of instructions cannot be generated with the current syntax. But it is a unit test which ensures that the embedded views are properly created after the container. So it is valid IMO.

});

describe('move', () => {
it('should work', () => {

Choose a reason for hiding this comment

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

could you think of a more descriptive name for this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

});

describe('get and indexOf', () => {
it('should work', () => {

Choose a reason for hiding this comment

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

could you think of a more descriptive name for this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

createView('B');
createView('C');
fixture.update();
fixture.hostElement.childNodes[1].nodeValue = '**A**';

Choose a reason for hiding this comment

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

Could we have, somewhere in a comment, how the template for this test looks like? I find it hard to see what this tests is asserting and if things are working correctly...

Choose a reason for hiding this comment

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

Maybe also add a comment explaining why we are doing DOM manipulation here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment and more expect to show all the steps of the test.

@pkozlowski-opensource
Copy link
Member

@marclaval I did the first pass on this PR, see my comments in the code. Looks good, generally speaking, IMO tests need more work (let's make sure that we are not duplicating those, add more comments etc.).

Also you will have to run gulp format to fix lint errors.

Since we are both touching the same area it would be great to have your opinion on #23193

@marclaval
Copy link
Contributor Author

All comments addressed, thanks for the review

@marclaval marclaval mentioned this pull request Apr 5, 2018
remove(index?: number): void {
const adjustedIdx = this._adjustAndAssertIndex(index);
this.detach(index);
// TODO(ml): proper destroy of the ViewRef
Copy link
Contributor

Choose a reason for hiding this comment

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

could you add to your comments what steps are missing from here. Otherwise this TODO becomes confusing in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

}
indexOf(viewRef: viewEngine_ViewRef): number { throw notImplemented(); }
indexOf(viewRef: viewEngine_ViewRef): number { return this._viewRefs.indexOf(viewRef); }
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Can you leave empty line between methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


describe('ViewContainerRef', () => {
class TestDirective {
constructor(public viewContainer: ViewContainerRef, public template: TemplateRef<any>, ) {}
describe('API', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the value of this additional describe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The goal is to group pure API tests, before adding more describe in future PRs, like projection, query, lifecycle hooks

@mhevery mhevery removed the action: review The PR is still awaiting reviews from at least one requested reviewer label Apr 5, 2018
@mhevery
Copy link
Contributor

mhevery commented Apr 5, 2018

Please add merge label once you take care of the nits


private _adjustAndAssertIndex(index?: number|undefined) {
private _adjustAndAssertIndex(index?: number|undefined, shift: number = 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should assert be in the name (it's a debug thing) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed

@ngbot
Copy link

ngbot bot commented Apr 5, 2018

Hi @marclaval! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

// +1 because it's legal to insert at the end.
ngDevMode && assertLessThan(index, this._lContainerNode.data.views.length + 1, 'index');
ngDevMode &&
assertLessThan(index, this._lContainerNode.data.views.length + 1 + shift, 'index');
Copy link
Contributor

Choose a reason for hiding this comment

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

refactor to have

if (ngDevMode && index !==null) {
// asserts
return index;
}

return  this._lContainerNode.data.views.length + shift;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This wouldn't work when ngDevMode is false

Copy link
Contributor

@vicb vicb Apr 6, 2018

Choose a reason for hiding this comment

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

Well yep there is an error in my extract but the point here is

  • multiple ngDevMode && does not help with readability,
  • especially when the else branch is empty in non dev mode

So maybe

if (index === null) return ...

if (ngDevMode) {
  // assert
}

return ...;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

constructor(private createBlock: () => void, private updateBlock: () => void = noop) {
constructor(
private createBlock: () => void, private updateBlock: () => void = noop,
directives?: DirectiveTypesOrFactory|null, pipes?: PipeTypesOrFactory|null) {
super();
this.updateBlock = updateBlock || function() {};
Copy link
Contributor

Choose a reason for hiding this comment

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

needed ? (defalut is noop)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@mary-poppins
Copy link

You can preview 157a25e at https://pr23189-157a25e.ngbuilds.io/.
You can preview 85c1c50 at https://pr23189-85c1c50.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 944452f at https://pr23189-944452f.ngbuilds.io/.

@marclaval marclaval added the action: merge The PR is ready for merge by the caretaker label Apr 6, 2018
@marclaval
Copy link
Contributor Author

Nits integrated and PR rebased.

One job is failing in Travis because of a bundle size issue, but the same is happening on master.
So I've added the merge label as suggested by @mhevery

@@ -40,6 +40,12 @@ export function assertLessThan<T>(actual: T, expected: T, msg: string) {
}
}

export function assertGreaterThan<T>(actual: T, expected: T, msg: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Generic really needed? Any possibility other than number for <= operator?

Copy link
Contributor

Choose a reason for hiding this comment

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

@trotyl Could be used for simple alphabetical sorting too, couldn't it? All the other assert functions are implemented the same way, so I suppose this is for consistency above all else.

Copy link
Contributor

@vicb vicb left a comment

Choose a reason for hiding this comment

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

see inline comments

@marclaval marclaval force-pushed the vcref_api branch 2 times, most recently from 5299f3c to a8619b3 Compare April 6, 2018 20:34
@mary-poppins
Copy link

You can preview a8619b3 at https://pr23189-a8619b3.ngbuilds.io/.

@marclaval
Copy link
Contributor Author

@vicb I did the change you requested, the PR should be good to go

@vicb
Copy link
Contributor

vicb commented Apr 7, 2018

@marclaval marclaval mentioned this pull request Apr 9, 2018
@IgorMinar IgorMinar closed this in f4c56f4 Apr 9, 2018
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants