apotomo
apotomo copied to clipboard
widget_div does not guarantee that HTML IDs are unique
Let's assume that we have the following widgets:
class AWidget < Apotomo::Widget
has_widgets do |root|
root << widget(:b, :b1)
root << widget(:b, :b2)
end
...
end
class BWidget < Apotomo::Widget
has_widgets do |root|
root << widget(:c)
end
...
end
class CWidget < Apotomo::Widget
...
end
Now I want to render_widget :a
. Assuming that each of these classes has a single display action that renders only a widget_div
, I get the following HTML structure:
#a
#b1
#c
#b2
#c
HTML IDs must be unique but this structure contains two DIVs with id c
.
Why not make widget names hierarchical so that we could get the following instead?
#a
#a_b1
#a_b1_c
#a_b2
#a_b2_c
This will change HTML IDs and therefore can break CSS for some people so there should be a configuration option bring back the old behavior.
With 1.2, you should be able to use root
and parent
in has_widgets
blocks to retrieve the ancestor chain.
Yes, this was already possible in 1.1.4. I am doing
has_widgets do |root|
root << widget(:a_widget, root.name.to_s + "_a_widget_instance")
end
This makes the code less readable though. Whenever I render a widget I have to do
render_widget controller.name.to_s + "_a_widget_instance"
I think the default behavior is dangerous because many users are not aware of this problem. Simply rendering two instances of a widget that contains a nested widget silently breaks your HTML IDs.
We could also enforce making ids unique when creating the widgets? If you compute an id dependent on the widget's position in the tree, you're also creating undesired side effects, I bet.
If you mean requiring user to always provide unique ID then no, its not possible. In BWidget you only name the nested CWidget once, but there may be multiple instances of it (that require different names) if BWidget is instantiated multiple times.
If you mean making it unique by appending something random to it or (like in my example in the original post) constructing it from the names of all widgets on the path to the root then yes, it's exactly what is needed here.
Something that gives the same effects as my workaround is enough. Just hide the controller.name.to_s + "_"
part inside render_widget()
and widget_div()
and root.name.to_s + "_"
in widget()
so that the user can refer to the widget is he does now.
https://github.com/apotonick/apotomo/blob/master/lib/apotomo/rails/view_helper.rb
you can set the css element id yourself:
def widget_div(options={}, &block)
options.reverse_merge!(:id => widget_id)
e.g.
widget_div(:id => 'something-unique') do
@camel Do you have a complete code example that would achieve what you are describing here?
Perhaps the options
argument to widget_div
could take a unique: true
option to use such a strategy?