Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Form $dirty and $valid broken with fields inside tabs #574

Closed
rosslavery opened this issue Jun 26, 2013 · 23 comments
Closed

Form $dirty and $valid broken with fields inside tabs #574

rosslavery opened this issue Jun 26, 2013 · 23 comments

Comments

@rosslavery
Copy link

I'm not sure if this is an implementation issue on my end, or a bug with the tabs directive, but I've asked around and most responses I've gotten seem to indicate it might be the latter.

When form fields are inside tabs, and that tabset is nested inside a <form>, the form's $dirty and $valid properties are not affected by the field(s) inside the tabset.

Plunkr here: http://plunker.co/edit/dCSE1jyLYIWY342mQfAl?p=preview

@pkozlowski-opensource
Copy link
Member

@ajoslin I think it might be related to #524
It would be happening if the NgModel can't find the form controller.

@rosslavery
Copy link
Author

I can confirm that the fix mentioned by @ajoslin in #524 has fixed this issue for me.

Adding $compile(tab.contentElement)(scope); fixes the issue.

@pkozlowski-opensource
Copy link
Member

OK, let's close this as a duplicate of #524 then

@rosslavery
Copy link
Author

Thanks for pointing me in that direction, wouldn't have found that otherwise - appreciated.

@rosslavery
Copy link
Author

This isn't fixed as I originally thought...

Compiling the tab.contentElement seems to break the bindings on certain fields.

From what I can tell, fields that are nested inside a tab, and then an ng-repeat seem to retain their bindings.

Those that are placed in the tab content area but NOT inside an ng-repeat don't display the values of their models.

@rosslavery
Copy link
Author

@pkozlowski-opensource, @ajoslin

Here's a plunker demonstrating the above issue:

http://plunker.co/edit/D6URYjfBQgtQ37nXQS1k?p=preview

Line 2434 of bootstrap.js in that plunker has the fix suggested in #524.

As you can see, on-load the initial value is bound in the "Form details" section, but the input itself doesn't get the value initially.

If you remove the line $compile(tab.contentElement)(scope); then the values are bound, but then the issue regarding $valid and $dirty on the form comes up again.

@ajoslin
Copy link
Contributor

ajoslin commented Jun 28, 2013

@rosslavery
Copy link
Author

I updated my plunkr with the latest tabs.js from be7ecff

http://plunker.co/edit/aEKvVwzHtcokTsYMMc2f?p=preview

In your test, I noticed that the ng-model values for the inputs were not properties of the same object defined in the parent scope.

In my plunkr, $scope.client is defined in the parent controller, and then both inputs are set to have ng-model values as properties of that object.

If I set the inner inputs ng-model to be $parent.client.email then it does dirty the form, but no longer has it's value bound.

@rkarakaya
Copy link

ng-options are duplicated inside tab!!
see this plunkr.
http://plunker.co/edit/frngp5?p=preview

@ajoslin
Copy link
Contributor

ajoslin commented Jul 8, 2013

The problem is the content elements are getting 'double-compiled'. Fixed that, working on a couple more fixes. Will commit soon :-)

@rkarakaya
Copy link

very nice..:-)
whole day, I was struggling this.

ajoslin added a commit that referenced this issue Jul 8, 2013
* Before, tab content was being transcluded before the tab content area
 was ready. This forced us to disconnect the tab contents from the DOM
 temporarily, then reocnnect them later. This caused a lot of problems.
* Now, neither the tab content or header are transcluded until both
 the heading and content areas are loaded. This is simpler and fixes
 many weird compilation bugs.
@ajoslin ajoslin closed this as completed Jul 8, 2013
@rkarakaya
Copy link

Thank you Andy. You saved my day:-)

@rosslavery
Copy link
Author

Thanks a lot @ajoslin . Working great now!

@nrdcp
Copy link

nrdcp commented Jan 22, 2014

It seems the issue has appeared back. I am having problems checking if the form located inside a tab is valid.

See the plunker: http://plnkr.co/edit/aMOayrmbPPqDlTtUyuks?p=preview

@Foxandxss
Copy link
Contributor

@nrdcp Tabs creates a new isolated scope and you're creating your form there. Setting something in a inner scope doesn't set it on the parent.

TL;DR; The controller's scope is not aware of any form at all.

@SaulBurgos
Copy link

Any luck with this bug? I have the same problem with 0.9 bootstrap ui

@nrdcp
Copy link

nrdcp commented Feb 12, 2014

@SaulBurgos As a workaround I ended up using the "tabset" directive and its templates from ui-bootstrap-tpls-0.6.0

@Foxandxss
Copy link
Contributor

Excuse me, what bug are we talking about? (@SaulBurgos, @nrdcp)

If it is the message from @nrdcp 3 weeks ago. No, that is not a bug.

@SaulBurgos
Copy link

Hi @Foxandxss
I am not sure if this is a bug because you said in your previous message this :

"Tabs creates a new isolated scope and you're creating your form there. Setting something in a inner scope doesn't set it on the parent. TL;DR; The controller's scope is not aware of any form at all."

But you did not say how to resolve this with a form inside a tabset. Ex: I want to access to my ngFormController of my scope to check the $valid and $dirty property of that form but the problem is how you said: tab create new isolated scope.

So my question for you would be : How can I access to my ngFormController inside a tabset ?

you can see the example here : http://plnkr.co/edit/HKyh1BJYL12knGMfkRq0?p=preview

@Foxandxss
Copy link
Contributor

The problem is Javascript inheritance. If I have an $scope and I put:

$scope.foo = "Hello";

And then I create a new scope that is child of that one and I do:

$scope.foo = "Bye";
$scope.meh = "Hi hi";

What would happen if I print foo in the child scope? Hello or Bye ? Bye Why? Because the child scope shadowed the parent foo. What happen if I print foo from parent? Hello The child is not overriding the parent, it is just creating a new copy for himself.

Ok, what happen if parent does a meh ? Nothing, he don't have any meh.

Having that knowledge. Your controller has a scope and the HTML inside the tab is transcluded, that mean that it has a child scope. Then ALL the rules I explained before applies.

What is happening in your plunker? In your first example you're creating a form in the child scope (like meh in my example). As you already know, the parent doesn't have that form in its scope so you don't see it.

In the second example, you're printing it from the child scope, so there of course you see it.

To make it work, is what we call the dot rule.

If you something like this in the parent:

$scope.foo = {
  bar: ''
}

And then this in the child:

$scope.foo.bar = "Hello";

You're NOT shadowing the parent in this case, it will get the parent's foo and then modify bar.

That is what you need to do here. Create a form using the dot rule and from the child just assign to it a new form.

Check here: http://plnkr.co/edit/R6v7EwQnQiDzK9HURqjL?p=preview
Read more: https://github.com/angular/angular.js/wiki/Understanding-Scopes

Read that, is much much explanation that I could give you here.

@SaulBurgos
Copy link

Thanks you for you explanation only for the record I made this example of how should work for everybody in the future:

http://plnkr.co/edit/HKyh1BJYL12knGMfkRq0?p=preview

some consideration that I think important :

  • You need to use the directive ng-form instead of an element form "".
  • The directive ng-form is not trigger the submit event, so it is not going to work the ng-submit() , you need to use a ng-click instead
  • the ng-model of inputs should be in another object, in my tests is the only way to get access to the ngModelControllers of the ngFormController of your form.

Well if I wrong please correct me, I am not a expert on angular :).

thanks @Foxandxss for your answer

@Foxandxss
Copy link
Contributor

I like it.

@amirensit
Copy link

Is this fixed with angular 2 because I face this problem.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants