简体   繁体   English

得到 <h:outputText> 作为支持bean的ManagedProperty

[英]get <h:outputText> as ManagedProperty in backing bean

First of all I want to say that I'm new in JSF. 首先,我想说我是JSF的新手。

I want to create simple composite component which will be available of editing articles. 我想创建一个简单的复合组件,可用于编辑文章。 It should work in this way: 它应该以这种方式工作:

  1. Composite component looks like this <my:article article="#{interestedBean.article}" /> 复合组件看起来像这样<my:article article="#{interestedBean.article}" />
  2. ArticleBean is responsible for procesing data of composite component (here is save method) ArticleBean负责处理复合组件的数据(这里是save方法)
  3. Each page which will want to use article need to add composite component to the view and Article object to the backing bean 想要使用文章的每个页面都需要将复合组件添加到视图,将Article对象添加到辅助bean
  4. Article object will be passed to the composite component and its value will be changed in ArticleBean Article对象将传递给复合组件,其值将在ArticleBean更改

The problem is that I don't know how to pass entity ( Article object) from one bean (interested bean) to another ( ArticleBean ) through view. 问题是我不知道如何通过视图将实体( Article对象)从一个bean(感兴趣的bean)传递到另一个( ArticleBean )。

Example (pseudocode; Lets imagine that Article entity is simple String object so we don't need to use converter): 示例(伪代码;让我们假设Article实体是简单的String对象,因此我们不需要使用转换器):

// input bean
public class HomePageBean {
    private Article article;
    @PostConstruct
    public void init() {
        this.article = new Article();
        this.article.setText("welcome on home page");
    }
    public void setArticle(Article article) {
        this.article = article;
    }
    public Article article() {
        return article; // on real page article will be taken from database
    }
}

// view
<h:form>
    <h:outputText value="#{articleBean.article.text}">
        <f:attribute name="value" value="#{homePageBean.article.text}" />
    </h:outputText>
</h:form>

// output bean
public class ArticleBean {
    private Article article;
    public void setArticle(Article article) {
        this.article = article;
    }
    public Article getArticle() {
        return article;
    }
    public void save() {
         // save article data to database
    }
}

// entity
public class Article {
    private article text;
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
}

The problem is that SecondBean.entity.text value is not set. 问题是未设置SecondBean.entity.text值。 How can I pass parameter to backing bean from view? 如何从视图中将参数传递给backing bean? I was trying to set Article value using @ManagedProperty(value="#{param.article}") but <h:outputText> is in form so the value is passed as randomformname:article . 我试图使用@ManagedProperty(value="#{param.article}")设置Article@ManagedProperty(value="#{param.article}")但是<h:outputText>处于表单中,因此值将作为randomformname:article传递。

Sorry for my English 对不起我的英语不好

Actually the question needs clarification. 实际上这个问题需要澄清。 So I've got two basic ideas on what you might want to do. 所以我对你可能想做的事情有两个基本的想法。

Simple sharing of information on one view 在一个视图上简单地共享信息

If you want to share information on the same view you can inject managed beans in each other with @ManagedProperty . 如果要在同一视图上共享信息,可以使用@ManagedProperty将托管bean互相注入。 Just remember that injected bean whould not have a lesser scope than the bean it is injected into. 请记住,注入的bean的范围不会小于注入的bean。 Actually, if all you need is an article object then I don't see the reason to use two managed beans in your situation, but still, you can do it with 实际上,如果您需要的只是一个文章对象,那么我没有看到在您的情况下使用两个托管bean的原因,但是,您仍然可以使用

@ManagedBean
@RequestScoped
public class BaseBean {

    private Article article;

    @ManagedProperty(value="#{injectedBean}")
    private InjectedBean injectedBean;

}

To initialize both properties of the managed beans that you want to be the same, you can use the init method annotated with @PostConstruct (but there are many alternatives), like in here 要初始化您想要相同的托管bean的两个属性,可以使用带@PostConstruct注释的init方法(但有很多替代方法),就像在这里一样

@PostConstruct
public void init() {
    Article article = new Article("Welcome");
    this.article = article;
    injectedBean.setArticle(article);
}

Share information between views 在视图之间共享信息

In this scenario the user selects an article he wants to edit on the first view and passes it around for the second view. 在这种情况下,用户在第一个视图上选择他想要编辑的文章, 并将传递给第二个视图。 In this scenario a user selectes an article he wants to manipulate on one page ( welcome.xhtml ) and the actual manipulation happens on the other page ( manipulation.xhtml ). 在这种情况下,用户选择他想要在一个页面上操作的文章( welcome.xhtml ),并且实际操作发生在另一页面上( manipulation.xhtml )。

The common approach is that each page is baced up by its own bean, so in the abovementioned setup the 'base bean' will lose its injection. 常见的方法是每个页面都被它自己的bean绑定,所以在上面提到的设置中,'base bean'将失去它的注入。 So, welcome.xhtml view will use some article objects that popped up on that page from somewhere and pass it for manipulation to the second view on button click. 因此, welcome.xhtml视图将使用从某个地方弹出该页面的一些文章对象,并在按钮点击时将其传递给第二个视图。

The beans will be the same with reagrd to the article object. bean与文章对象的reagrd相同。

@ManagedBean
@RequestScoped
public class BaseBean {

    private Article article;

}

@ManagedBean
@RequestScoped
public class InjectedBean {

    private Article article;

}

And the actual passing will happen during the button click, like in 实际传递将在按钮点击期间发生,例如

    <h:form>
        <h:commandButton value="Manipulation" action="manipulation.xhtml">
            <f:setPropertyActionListener target="#{injectedBean.article}" value="#{baseBean.article}"/>
        </h:commandButton>
    </h:form>

In the code, the property action listener method is instantiating a bean for the second view and sets it property with the property of a base bean. 在代码中,属性动作侦听器方法是为第二个视图实例化一个bean,并使用基本bean的属性设置它的属性。

Using get parameters for page loading 使用get参数进行页面加载

Sometimes it makes more sence not to include a command button to trigger navigation to the next view, but provide for a simple link to editing the page. 有时它更多的是不包括命令按钮来触发导航到下一个视图,但提供了编辑页面的简单链接。 It may be achieved by using <f:param> tag. 它可以通过使用<f:param>标签来实现。 There are two basic ways of handling parameters in JSF: by using page actions / preRenderView events or by injecting them directly in your managed beans with @ManagedProperty . 在JSF中有两种处理参数的基本方法:使用页面操作/ preRenderView事件或使用@ManagedProperty直接在托管bean中注入它们。

  1. Using Page actions / preRenderView events 使用Page actions / preRenderView事件

The job will be done by the target view 作业将由目标视图完成

<f:metadata>
    <f:viewParam id="articleId" name="articleId" value="#{injectedBean.id}" />
    <f:event type="preRenderView" listener="#{injectedBean.initEvent}" />
</f:metadata>

for preRenderView event and 对于preRenderView事件和

<f:metadata>
    <f:viewParam id="articleId" name="articleId" value="#{injectedBean.id}" />
    <f:viewAction action="#{injectedBean.initEvent}" />
</f:metadata>

for page action. 用于页面操作。 The managed bean ( InjectedBean object) will have the following init method 托管bean( InjectedBean对象)将具有以下init方法

public void initEvent() {
    if (id == null) {
        String message = "No id specified in request";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));
        return;
    }
    //use your service method to load the article
    //article = articleService.findById(id);
    //and add messages appropriately
}
  1. Using @ManagedProperty annotation 使用@ManagedProperty注释

The job will be done by the following bean method, annotated with @PostConstruct , and parameter dependency injection. 该作业将通过以下bean方法完成,该方法使用@PostConstruct注释,并且参数依赖注入。 Remember, for the setup to work the bean must be @RequestScoped , but there are workaround for other bean scopes. 请记住, @RequestScoped设置正常工作,bean必须是@RequestScoped ,但是有其他bean范围的解决方法。

@ManagedProperty(value="#{param.articleId}")
private Integer id;

@PostConstruct
public void initPostConstruct() {
    if (id == null) {
        String message = "No id specified in request";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));
        return;
    }
    //use your service method to load the article
    //article = articleService.findById(id);
    //and add messages appropriately
}

Any way the bean will be initialized during the next view ( manipulation.xhtml ). 在下一个视图( manipulation.xhtml )中初始化bean的任何方式。 Extremely useful comparison of these two ways, provided by BalusC, can be found here . 由BalusC提供的这两种方式的非常有用的比较可以在这里找到。

Navigation to this view may be handled, for example, via a simple <h:link> , like in 例如,可以通过简单的<h:link>处理对该视图的导航,例如

<h:link value="Manipulate" outcome="manipulation.xhtml" >
    <f:param name="articleId" value="#{baseBean.article.id}" />
</h:link>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM