如何使用动态参数为页面提供面包屑?

时间:2015-07-31 21:33:47

标签: html grails groovy breadcrumbs

我找到了一个Grails框架来生成Breadcrumbs here。它确实根据breadcrumbs.xml文件中的静态定义生成面包屑,它定义了面包屑的层次结构:

     <map>
        <nav id="homeCrumb" matchController="samplePages" matchAction="homeBreadCrumbPage">
            <!-- levels navigation -->
            <nav id="itemsLevel1Crumb" matchController="samplePages" matchAction="level1BreadCrumbPage">
                <nav id="itemsLevel2Crumb" matchController="samplePages" matchAction="level2BreadCrumbPage">
                    <nav id="itemsLevel3Crumb" matchController="samplePages" matchAction="level3BreadCrumbPage">
                        <nav id="showItemCrumb" matchController="samplePages" matchAction="itemDetailsBreadCrumbPage"/>
                    </nav>
                </nav>
            </nav>
            <nav id="simple1Crumb" matchController="samplePages" matchAction="simpleBreadCrumb"/>
            <nav id="simple2Crumb" matchController="samplePages" matchAction="simpleBreadCrumbWithAttr"/>
            <!-- levels navigation -->
        </nav>
    </map>

此文件由taglib评估和打印:

class BreadCrumbTagLib {

    static def log = LogFactory.getLog("grails.app.breadCrumbTag")

    def breadCrumb = { attrs , body ->

            def manager = BreadCrumbManager.getInstance()
            def uri = request.getRequestURI() 
            def context = request.getContextPath() 

            def controller = params.controller
            def action = params.action

            def attrTitle =  attrs.title
            def attrLink = attrs.link

            // if controller and action are missing from params try to get them from request url
            if (!controller && !action && uri && context && uri.indexOf(context) != -1) {
                def uriParams = uri.substring(uri.indexOf(context) + (context.length() + 1), uri.length())
                def uriArray = uriParams.split('/')

                if (uriArray.size() >= 2 ) {
                    controller = uriArray[0]
                    action = uriArray[1]                       
                }
            }

            def crumbs = manager.getBreadCrumbs(controller, action)

            if (crumbs) {
                out << '<div class="breadcrumb"><ul>'
                def size = crumbs.size()
                crumbs.eachWithIndex { crumb, index ->
                    out << '<li>'

                    // override title and link of breadcrumb on current page (i.e. last bread crumb in hierarchy)
                    // if name, link attributes are supplied
                    if (index == size - 1) {
                        if (attrTitle)
                            crumb.title = attrTitle
                        if (attrLink)
                            crumb.link = attrLink
                    }
                    // set title to undefined if not found, associated 
                    // renderer if present can overwrite it
                    if (!crumb.title)
                        crumb.title = "undefined"
                    if (crumb.title && crumb.title.size() > 40)
                        crumb.title = crumb.title.substring(0, 40) + "..."

                    if (crumb.viewController && crumb.viewAction) {
                        def content = g.include(controller:crumb.viewController, action:crumb.viewAction, breadcrumb:crumb, params:params)
                        out << content
                    } else if (crumb.viewTemplate) {
                        def content = g.include(view:crumb.viewTemplate, breadcrumb:crumb, params: params)
                        out << content
                    } else if (crumb.linkToController && crumb.linkToAction && (size - 1 > index)){
                        out << "<a href=\"${g.createLink (controller: crumb.linkToController, action: crumb.linkToAction)}\">${crumb.title}</a>"
                    // if crumb has a link and its not the last vread crumb then show link else
                    // just show the text
                    } else if (crumb.link && (size - 1 > index)){
                        out << "<a href=\"${crumb.link}\">${crumb.title}</a>"
                    } else {
                        out << "${crumb.title}"
                    }
                    out << "</li>"
                    // do not print for last bread crumb
                    if (size - 1 > index)
                        out << "<li>&raquo;</li>"
                }
                out << "</ul></div>"
            }
    }
}  

问题:当我有一个结构,我需要一些没有修复的参数。

示例:我处于第三级导航中,可以说

A1 / A2 / A3

在我的情况下A2应该打开像user/show/1234这样的页面,其中1234是要显示的用户的ID。问题是我无法在breadcrumbs.xml文件中添加1234硬编码,因为此ID会根据您要显示的用户而改变。

如果中间面包屑链接需要动态参数,我该如何处理?

3 个答案:

答案 0 :(得分:1)

看起来您的面包屑的格式为CONTROLLER / ACTION / ID。如果是这样,您需要的信息已通过webRequest属性在您的GSP中提供。以下是使用Twitter Bootstrap面包屑的示例:

<ol class="breadcrumb">
  <li><a href="#">${webRequest.controllerName}</a></li>
  <li><a href="#">${webRequest.actionName}</a></li>
  <li class="active">${webRequest.id}</li>
</ol>

您仍然需要将href设置为有意义的内容。一种更强大的方法就是这样......

<g:set var="crumbs" value="${[webRequest.controllerName, webRequest.actionName, webRequest.id].findAll { it != null }}.collect { [label: it, active: false] }" />
<% crumbs.last().active = true %>
<ol class="breadcrumb">
    <g:each in="${crumbs}">
        <li class="${it.active ? 'active' : ''}"><a href="#">${it.label}</a></li>
    </g:each>
</ol>

通过&lt; %%&gt;将Groovy代码嵌入到GSP中不建议使用标签,但可以在TagLib中完成此类操作。这种方法可以处理长度为1-3个部分的面包屑。它根据当前URI进行调整。

答案 1 :(得分:1)

在考虑了一些之后,我意识到最好不要使用HttpSession。如果您使用会话范围的服务,则更容易对面包屑代码进行单元测试。

首先,创建一个会话范围的服务来维护用户的导航历史记录。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:drawSelectorOnTop="false"
    />

  <android.support.design.widget.FloatingActionButton
    android:id="@+id/refresh"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|right"
    android:layout_marginBottom="@dimen/fab_margin"
    android:layout_marginRight="@dimen/fab_margin"
    android:src="@drawable/ic_refresh_black_24dp"/>

</android.support.design.widget.CoordinatorLayout>

在您的控制器中注入服务并使用它来跟踪用户的位置。然后将历史记录添加为动作模型返回的内容的一部分:

class NavigationHistoryService {
    static transactional = false
    static scope = "session"

    def history = [:]

    public List push(String controller, String action, Map params) {
        def crumb = [
            action: action, 
            params: params]

        history.controller = crumb

        return history
    }   

最后,使用GSP中的历史记录来渲染碎屑。

class CompanyController {
    def navigationHistoryService

    def show() {
        navigationHistoryService.push('company', 'show', params)
        ...
        [crumbs: navigationHistoryService.history] 
    }
}

答案 2 :(得分:0)

use simple by blade view
 <ul class="breadcrumb" style="padding-right: 20px">
                <li> <i class="fa fa-home"></i> <a class="active" href="{{url('/')}}">Home</a>
                    {{--<i class="fa fa-angle-right"></i>--}}
                </li> <?php $link = url('/') ; ?>
                @for($i = 1; $i <= count(Request::segments()); $i++)
                    <li>
                        @if($i < count(Request::segments()) & $i > 0)
                            <?php $link .= "/" . Request::segment($i); ?>
                                <a class="active" href="<?= $link ?>">{{Request::segment($i)}}</a>
                                {{--{!!'<i class="fa fa-angle-right"></i>'!!}--}}
                        @else {{Request::segment($i)}}
                        @endif
                    </li>
                @endfor
            </ul>