Dropdown menu creation with alchemy cms

303 views
Skip to first unread message

Nuno Brito

unread,
Jun 9, 2015, 2:15:44 PM6/9/15
to alche...@googlegroups.com
Dear all,
Is there any way to create a dropdown menu element (using bootstrap), so the user can add elements to it?
I can now add and remove buttons dynamically such as:

- name: horizontal_header_bar
  unique: true
  available_contents:
  - name: button
    type: EssenceText
    settings:
      linkable: true
      deletable: true
  - name: image
    type: EssencePicture
    take_me_for_preview: true
    settings:
      linkable: true
      deletable: true

However, the dropdown menu is like a element inside another element... how is it possible? Can I make another hierarchy level below he button element on the above example?
Thank you all for your attention,
Nuno

Nuno Brito

unread,
Jun 11, 2015, 5:47:42 AM6/11/15
to alche...@googlegroups.com
Hello all,
I feel like I am close to the solution... I can add and remove buttons and dropdown buttons. But I am facing an isse, but before that, what I did:

#page_layouts.yml
- name: header
  unique: true
  layoutpage: true
  #elements: [header_bar]
  elements: [header_image, header_button, header_dropdown]

#Elements.yml
- name: header_dropdown
  contents:
  - name: button_text
    type: Alchemy::EssenceText
    settings:
      linkable: true
  available_contents:
  - name: dropdown_button
    type: EssenceText
    settings:
      linkable: true

- name: header_image
  contents:
  - name: image
    type: EssencePicture
    take_me_for_preview: true
    settings:
      linkable: true

- name: header_button
  contents:
  - name: button
    type: EssenceText
    settings:
      linkable: true

Now, the views:
#views/alchemy/elements/_header_dropdown_view.html.erb
<%- cache(element) do -%>
    <%= element_view_for(element, tag: false) do |el| -%>
        <li class="dropdown">
          <%= el.render :button_text %>
          <ul role="menu" class="sub-menu">
            <%- element.contents.where(name: ['dropdown_button']).each do |content| -%>
              <li><%= render_essence_view(content) %></li>
            <%- end -%>
          </ul>
        </li>
    <%- end -%>
<%- end -%>

#views/alchemy/elements/_header_bar_view.html.erb
<p>render _header_bar</p>
<%- cache(element) do -%>
  <%= element_view_for(element) do |el| -%>
    <%- element.contents.where(name: ['image', 'button', 'header_dropdown']).each do |content| -%>
      <%= render_essence_view(content) %>
    <%- end -%>
  <%- end -%>
<%- end -%>

And then in the index layout, I added the header global page rendering

#views/alchemy/page_layouts/_index.html.erb
<header id='header'>
  <%= render_elements from_page: 'header' %>
</header>
<%= render_elements %>


And now in the global page edit preview, the header page works very well, with the dropdown working fine.



But the problem is now with the rendering of the page itself... it renders the items separately and not the _header.html.erb layout, which is responsible to arrange the items in a header bar!

What am I doing wrong and how do the global pages and the page layout fit together?
Thank you for your help,
Nuno

flocutus

unread,
Jun 11, 2015, 7:07:53 AM6/11/15
to alche...@googlegroups.com
Hello Nuno,

I hope I can help because I had a similiar problem. Maybe this is a way to verify if I solved this in a good way.

I overwrote the views at views/alchemy/navigation/_renderer.html.erb and views/alchemy/navigation/_link.html.erb which look as following now:

#views/alchemy/navigation/_renderer.html.erb
<% if pages.present? %>
<% level = pages.first.level - 1 %>
<%= content_tag(
'ul',
:class => html_options[:class] || options[:dropdown] ? "dropdown-menu" : "nav navbar-nav level_#{level}",
:id => html_options[:id]
) do %>
<% pages.each do |page| %>
<% position = 'first' if page == pages.first %>
<% position = 'last' if page == pages.last %>
<% dropdown = !page.first_public_child.nil? %>
<% options[:dropdown] = dropdown %>
<%= content_tag(
'li',
:class => [page.slug, position, page_active?(page) ? 'active' : nil, dropdown ? 'dropdown' : nil, level > 1 ? 'dropdown-submenu' : nil].compact.join(' ')
) do %>
<%= render options[:navigation_link_partial], :page => page, :options => options %>
<% options[:from_page] = page %>
<% if options[:reverse_children] %>
<% options[:reverse] = true %>
<% end %>
<% if options[:show_nonactive] %>
<%= render_navigation(options) if options[:submenu] %>
<% else %>
<%= render_navigation(options) if (options[:submenu] && page_active?(page)) || options[:all_sub_menues] %>
<% end %>
<% end %>
<% if options[:spacer].present? && position != 'last' %>
<%= content_tag :li, options[:spacer].html_safe, class: 'navigation_spacer' %>
<% end %>
<% end %>
<% end %>
<% end %>


#views/alchemy/navigation/_link.html.erb

<% dropdown = options[:dropdown] %>
<% if page.redirects_to_external? %>
<%= link_to(
h(page.name),
dropdown ? "#" : page.urlname,
:title => options[:show_title] == true ? page.title : nil,
:target => configuration(:open_external_links_in_new_tab) ? '_blank' : nil,
:class => external_page_css_class(page).join(( dropdown ? "dropdown-toggle" : nil))
) %>
<% else %>
<%= link_to(
h(page.name),
@preview_mode ? 'javascript: void(0)' : (dropdown ? "#" : show_alchemy_page_path(page)),
{
:class => "#{(page_active?(page) ? 'active' : nil)} #{dropdown ? 'dropdown-toggle' : nil}",
:title => (options[:show_title] ? page.title : nil),
:lang => page.language_code,
:data => {'page-id' => page.id},
"data-toggle" => dropdown ? "dropdown" : nil
}
) %>
<% end %>

This is my first post but I hope I gathered all information that is needed.

All the best

Flo

Nuno Brito

unread,
Jun 11, 2015, 7:16:20 AM6/11/15
to alche...@googlegroups.com
Hi Flo,
Thank you for your help, but I don't feel confident about that approach because I would like to avoid overriding the Alchemy core files.
This can work now, but it is a headache to update and keep the project in sync.
I think that I may be able to achieve this using layouts and elements, which is what alchemy is all about.
And as I said, I feel like I am pretty close to do it.
I would like to hear the opinion of the project managers/contributers to understand what is the prefered solution.
I also think that my problem is relatively basic one... I am missing something related to the way alchemy renders pages.
Thank you once again ;)
Best,
Nuno

Nuno Brito

unread,
Jun 11, 2015, 7:50:03 AM6/11/15
to alche...@googlegroups.com
It seems to be working now.
What I did was (added code is as bold and underlined):
views/alchemy/page_layouts/_header.html.erb:

<%= render 'alchemy/page_layouts/header' %>
<%= render_elements %>

views/alchemy/page_layouts/_header.html.erb:
<div class="navbar navbar" role="banner">
    <div class="container">
      <div class="navbar-header">
        <a class="navbar-brand" href="/">
          <h1>
            <%= render_elements from_page: 'header', only: ['header_image'] %>
          </h1>
        </a>
      </div>
      <div class="collapse navbar-collapse">
        <ul class="nav navbar-nav navbar-right">
          <%= render_elements from_page: 'header', only: ['header_button', 'header_dropdown'] %>
        </ul>
      </div>
    </div>
  </div>

It seems to be working find on both the editor preview and the index.html public page rendering!
Thank you all for your support and any doubt, you can ask.
Best regards,
Nuno


terça-feira, 9 de Junho de 2015 às 19:15:44 UTC+1, Nuno Brito escreveu:
Reply all
Reply to author
Forward
0 new messages