Link to home
Start Free TrialLog in
Avatar of RationalRabbit
RationalRabbit

asked on

Multiple jQuery Bootstrap Forms on Same Page

I am using a jQuery tabs package (SolidTabs) to present several jQuery/BootStrap (BootGrid) Ajax forms on the same page. iframes are not an option. As its name implies, BootGrid displays a table of records, along with the ability to add a new record or edit an existing one, taking advantage of Ajax, using json and PHP.
I have not wanted to mess with the main js file. I'm thinking I should just be able to change the various HTML id's, and I should be fine. So far, that has not been successful.

My perhaps naive question is - other than using an iframe, is there some way of containing these separate grid forms so that I could use the same id assignments on the same page?
Avatar of zephyr_hex (Megan)
zephyr_hex (Megan)
Flag of United States of America image

No.  it is invalid to have more than one element on a page with the same id.  You may, however, be able to use a class.  Classes are designed to allow multiple elements with the same class.
Avatar of Marco Gasi
Not sure if I have understood so let me summarize. In the same age you have several forms in differents tabs. The user can add fields to the current form and this is done through an Ajax call performed by jQuery. Since the forms have the same id, the new field is added to every form and not only to the current one.

If this is the case you could use a class instead of an id (ids must be unique). I guess the current tab will have a class 'active', so you could use a selector like
$('tab.active .my-form').append();

Open in new window


Could this help?
Avatar of RationalRabbit
RationalRabbit

ASKER

Thanks for the input, Megan. Changing Id's to classes would probably be more difficult, though, than just changing the ID names. I'm dealing with both BootStrap and BootGrid here, so probably wouldn't be too good to stray too far from their structure.
Bootstrap supports classes.

In the case of BootGrid, for example, you'd just change your initializer from an Id to a Class.

So, for example, from this:

$("#grid-selection").bootgrid({

Open in new window


To this:

$(".grid-selection").bootgrid({

Open in new window


Where "grid-selection" is a class on your table elements (and not an id)
Yes, that works, but is it any different than just changing the id name?
Where I am really running into problems is every field (although there are only 5 in the table I am currently working with), has a set of id's - normal id (identical to the field name) and "edit_"{field name}, then there are other id's for buttons etc., but it's not like it is a complex form, so my first attempt was just to go through and preface every id with a name defining that table. Somewhere, this caused the system to hang, so I have started over, just changing a few at a time.
Yes, it's different than using id's because an id MUST be unique.  If you have more than one element on a page with the same id, it's invalid HTML and can lead to unexpected results, especially when you bring jQuery / JavaScript into the picture.
Classes are mean to be used when you have multiple elements that you want to target.  

If your code relies on finding  related elements by id (such as a button in a row), you may need to adjust your code to account for DOM traversal in order to find an element in the same row as the targeted element.  Or, if you don't have any type of relational requirements, you may be able to get away with just swapping out your id's for classes.
Can you paint a picture of what your end result is supposed to be?  Perhaps a line drawing, screenshot etc?  

On a side note, If you are using a form in a table with bootstrap, I think you are defeating the purpose of using a responsive grid.  If you are using the table to line things up, just use bootstrap's grid in place of the table.
Megan - I don't think you understood my question when I said "Yes, that works, but is it any different than just changing the id name?"
I understand quite well the difference between id's and classes. Thus, my question.  It is much less complicated to change the id name so that each grid has a unique ID than to substitute classes for id's, and you would still have to have unique classes.

Doing a file text search, it appears that the id names are not specified in the BootGrid.js file. I just have to take this a few variables - or rather, Id's at a time and figure out where the problem is. I was hoping there was some unique isolation within a page that I wasn't aware of that, of course, would make it all easier.

Scott - Good advice. I just pulled the code structure from here: https://www.phpflow.com/php/addedit-delete-record-using-bootgrid-php-mysql/#comment-559928
It is much less complicated to change the id name so that each grid has a unique ID than to substitute classes for id's

WHY ?  One class is far simpler than a bunch of unique id's...

Think of it this way... whenever you code something, you should stop and question yourself:
1.  Is this maintainable ?  If I have to add more to it, how hard would it be to change?
2.  Can my approach be simplified ?  The less complex, the more maintainable, and the fewer the changes for bugs.
3.  Can I use a pattern or function to reduce repeated code ?  Any time you are re-using the same code, it should be a red flag to stop and review what you're doing, and look for a way to replace the repeated code with one function that does the work.

Having a bunch of unique id's is not simpler than using one class.
Certainly agree with you regarding repetitive code. Perhaps I am not understanding due to my elementary coding practices.
I assume what you are saying is, when using a class, I can use "this" and it will be specific to the form that the class resides in, no?.
But, if you have something like this:
<div class = "div1">div1 content</div>   <div class = "div1">div2 content</div>
and you need to change the innerHTML of that div to coincide with the form,  I'm not sure how you would do that.
Hope I have explained that well enough.
It depends on what element the event is bound to.  If the event is bound to a click action on a div, "this" is the div that was clicked.  You can change the innerHTML using "this".

Here's an example using the HTML in your last post:

https://jsfiddle.net/zephyr_hex/hL59eez5/

$(document).ready(function() {
  $('.div1').on('click', function() {
    $(this).html("You clicked me!");
  });
});

Open in new window


When you click a div, the text is changed.  "this" is the element that was clicked.

If, however, you bind an event to a table row click, but you want to take action on a button in a cell in that row, you will need to use DOM navigation to find the button in "this" (where "this" is the row).
I will think on that and try to come up with a better (working) example. Right now, the project has been put on the back shelf until the first of the week.
Here's where I get confused.
Let's say we have this, as part of the BootGrid.js file that defines the basic grid configuration: <button class="AddItem">Add Item</button>,
and I have the following:
$('.AddItem').on('click', function() {
    This needs to open an item entry form, which happens in a modal window
    But I have no idea (other than using a global or dynamically adding/removing classes
    in the structure js code,  how to tell it which grid the click relates to    
});

Open in new window

This thread is getting off track.  

Let's put everything else aside (bootgrid / bootstrap) because that is confusing the issue somewhat.  Your question is, " is there some way of containing these separate grid forms so that I could use the same id assignments on the same page"

As it has been said, the answer is no.  

Please refer to the spec https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#the-id-attribute
The id attribute specifies its element's unique identifier (ID). The value must be unique amongst all the IDs in the element's home subtree and must contain at least one character. The value must not contain any space characters.

Yes, physically you can put in multiple id's and you will not be taken away by the html police, but your page will run into issues especially when using jquery which traverses and updates the DOM.

Many examples for plug ins tend to use id's $('#some_id').someFunction():  But if you need to target multiple items, then you will use class. You shouldn't update the plugin's main javascript file and instead update the way you call that function.  The information you have been given so far is the solution.
ASKER CERTIFIED SOLUTION
Avatar of zephyr_hex (Megan)
zephyr_hex (Megan)
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Scott - The original question was SOMETHING like, as you stated "is there some way of containing these separate grid forms so that I could use the same id assignments on the same page", but not exactly. I was curious if there was some technique I was not aware of that could create the effect of an iframe without the iframe. :0)  At any rate, that was resolved at the beginning of the thread,so it moved on. The thread HAS strayed in other ways, however, due to my avoidance of taking the time to really understand object oriented programming, or dealing much with DOM navigation and it is now biting me pretty badly. It's quite embarrassing and I feel like I'm out in left field.

Megan Simple, no?  Thanks for putting up with me. That should do it. Sorry to be so confusing.
>  It's quite embarrassing and I feel like I'm out in left field.

Just know we were all there at one time.  And the only way to to get better is by constant practice and not being afraid to make mistakes in order to learn.

The reason for my statement to keep things on track is just that. It's possible there are more "learning experiences" here, but it is best to attack each one individually in it's own thread.  That makes it easier on  you and the Experts.
Thanks, Scott.