4

I don't know how to phrase a better title as I'm obviously not fully understanding what is happening.

Given this plunkr where I recreated my issue:
http://plnkr.co/edit/vaj5peVpteYQx4iZd3pw?p=preview

this.items.splice(i, 1); -> refresh  
this.items.splice(i - 1, 1); -> or any other i (not the target of the method) no refresh

Somebody can explain to me why:
Adding a Cabron is fine.
Removing a Cabron with the removeALT method is fine.
But instead removing the same Cabron with the default remove Cabron button forces a page refresh?

To reproduce:
1) Click "add Hello" (not part of the test actually)
2) Click "Less Cabron" and the page will refresh.
2 OR) Click either "More Cabron" or "Less Cabron ALT" and the page will not refresh (despite the form being changed and being very similar to "Less Cabron").

I'm trying to give the possibility to add/remove/moveup/movedown fields in a form.

I could do weird things with css and always use the "i +/- x", but I would prefer to understand how to avoid this.
Also on my application (that is run on an external window [window.open()]) the url of the window changes with the parameters of the spliced object passed as URL parameters (no idea why).

example: [starting url, after here is all inserted from that bug]?title=Cabron
Kunepro
  • 418
  • 2
  • 4
  • 18

1 Answers1

4

You should add type="button" to your buttons so they are not rendered as submit buttons. If the type="submit" it could trigger a page postback to the server.

Example

<button type="button" (click)="add(i)">More Cabron</button>

Doing this fixes the problem.


Alternatively you can pass the event args to the button click handler and call preventDefault() on that event arg.

Html

<button (click)="add(i,$event)">More Cabron</button>

Code

add(i,$event) {
  $event.preventDefault();
  // rest of code

From the documentation for Button

Tip: Always specify the type attribute for a element. Different browsers use different default types for the element.

So what happens to a button depends on the browser if you fail to set the button's type, you are leaving it up to chance at that point.


(from comment) ...splice(i, 1) always triggers the page refresh. splice(anotherElement,1) never does, should we leave this as "Angular magic"?...

That is because those buttons are nested in a form and as type is not defined the browser you are using defaults the type to submit which causes a form postback. The initial button you have (that does not cause a post back) is not in a form so the browser is not treating it as a submit button.

Igor
  • 60,821
  • 10
  • 100
  • 175
  • You have to tell my why this does not happen with the other 2 buttons. None of the buttons have the type set. – Kunepro Jan 27 '17 at 16:12
  • This fixes the problem, but it's not a matter of changes. splice(i, 1) always triggers the page refresh. splice(anotherElement,1) never does, should we leave this as "Angular magic"? – Kunepro Jan 27 '17 at 16:18
  • @Netscreever - I would saw its `browser interpretation`. Also maybe there is something in the angular lib. that already calls `preventDefault` somewhere, really not sure. The only thing I am sure of is that it is always best to either provide the type and when you use type `submit` to call preventDefault if you do not actually want to submit the page. – Igor Jan 27 '17 at 16:20
  • 1
    I agree with what you are saying, the type should always be defined, shame on me. Your solution allows me to move on, and I'm happy with it. But I would also like to understand behind the scene, however probably I will not get that answered, so I'm happy with this. – Kunepro Jan 27 '17 at 16:22
  • @Netscreever - updated answer. The first button does not do a post back because it is not defined inside of a `form` tag. The other buttons do execute a postback because they are defined in a `form` tag. This might be browser specific but that is the way your browser is treating the buttons. – Igor Jan 28 '17 at 13:08
  • All the buttons are defined the same way inside a form tag. I know that the "thing" doesn't happen if the are out of a form tag, that is why creating this plunkr I recreated the form, but I don't understand what you mean when saying that only 1 of them is inside the form as that's not true. – Kunepro Jan 30 '17 at 11:57
  • @Netscreever - I think you miss-read. There is 1 button that does not cause a post back, the initial button. This button is created in your component `App` and is not nested inside of a `form` element. All other buttons are loaded in `HelloComponent` and those are nested inside of a `form` tag and because these do not have `type` defined they are treated as `type="submit"` by your browser and cause a `postback`. That explains why one button (initial button) does not cause it but the others do. – Igor Jan 30 '17 at 12:01
  • ok, but ignore the initial button, it shouldn't have been there in the first place. The other 3 buttons that are repeated in set "More Cabron", "Less Cabron" & "Less Cabron ALT" are all in the form, yet only 1 of those buttons causes the page refresh, "Less Cabron". "Less Cabron ALT" is always in the form, like "Less Cabron", and the code is almost the same, yet it does not refresh the page. – Kunepro Jan 30 '17 at 13:29
  • @Netscreever - got it, ok. Well, i guess the answer is "browser magic", that is the browser determines what it will do to what button, odd that it picks the middle one though. – Igor Jan 30 '17 at 13:40