การทำความเข้าใจกับกระบวนการ PrimeFaces / อัพเดตและแอ็ตทริบิวต์ JSF f: ajax execute / render


194

สิ่งที่ว่าprocessและupdateใน PrimeFaces p:commandXxxส่วนประกอบและexecuteและrenderในf:ajaxแท็ก?

ช่วงเวลาใดของการตรวจสอบความถูกต้อง อะไรupdateแอตทริบิวต์ทำมากกว่าการปรับปรุงมูลค่าให้กับส่วนประกอบจากปลายกลับมา? ทำprocessค่าแอตทริบิวต์ผูกกับรูปแบบ? ว่าทำอย่างไร@this, @parent, @allและ@formในคุณลักษณะทั้งสอง?

ตัวอย่างด้านล่างใช้ได้ดี แต่ฉันสับสนเล็กน้อยในแนวคิดพื้นฐาน

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />

คำตอบ:


307

<p:commandXxx process> <p:ajax process> <f:ajax execute>

processแอตทริบิวต์ฝั่งเซิร์ฟเวอร์และสามารถส่งผลกระทบเพียงUIComponents การดำเนินการEditableValueHolder(ช่องใส่) หรือActionSource(ทุ่งคำสั่ง) processแอตทริบิวต์บอก JSF โดยใช้รายการพื้นที่ที่คั่นของรหัสลูกค้าซึ่งส่วนประกอบว่าจะต้องดำเนินการผ่านวงจร JSF ทั้งหมดเมื่อ (บางส่วน) ส่งแบบฟอร์ม

จากนั้น JSF จะใช้ค่าคำขอ (การค้นหาพารามิเตอร์คำขอ HTTP ขึ้นอยู่กับ ID ไคลเอ็นต์ของส่วนประกอบและจากนั้นตั้งค่าเป็นค่าที่ส่งในกรณีของEditableValueHolderส่วนประกอบหรือจัดคิวใหม่ActionEventในกรณีของActionSourceส่วนประกอบ) ทำการแปลงตรวจสอบและอัพเดทค่ารุ่น ( EditableValueHolderส่วนประกอบเท่านั้น) และในที่สุดก็เรียกคิวActionEvent( ActionSourceส่วนประกอบเท่านั้น) JSF จะข้ามการประมวลผลของส่วนประกอบอื่น ๆ ทั้งหมดที่ไม่ได้รับการคุ้มครองโดยprocessคุณลักษณะ นอกจากนี้ส่วนประกอบที่มีแอrenderedททริบิวต์ประเมินfalseระหว่างช่วงคำขอการใช้ค่าจะถูกข้ามไปด้วยซึ่งเป็นส่วนหนึ่งของการป้องกันการร้องขอที่ดัดแปลง

โปรดทราบว่าในกรณีของActionSourceองค์ประกอบ (เช่น<p:commandButton>) สำคัญมากที่คุณจะต้องรวมองค์ประกอบเองไว้ในprocessแอตทริบิวต์โดยเฉพาะถ้าคุณตั้งใจจะเรียกใช้การกระทำที่เกี่ยวข้องกับส่วนประกอบ ตัวอย่างด้านล่างซึ่งมีเจตนาที่จะดำเนินการเฉพาะองค์ประกอบอินพุตบางอย่างเมื่อมีการเรียกใช้องค์ประกอบคำสั่งบางอย่างซึ่งจะไม่ทำงาน:

<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="foo" action="#{bean.action}" />

มันจะประมวลผล#{bean.foo}และไม่ #{bean.action}คุณจะต้องรวมองค์ประกอบคำสั่งด้วยเช่นกัน:

<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="@this foo" action="#{bean.action}" />

หรืออย่างที่คุณรู้ว่าใช้@parentถ้ามันเป็นเพียงส่วนประกอบที่มีพาเรนต์ร่วม:

<p:panel><!-- Type doesn't matter, as long as it's a common parent. -->
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@parent" action="#{bean.action}" />
</p:panel>

หรือหากทั้งคู่เป็นเพียงส่วนประกอบของUIFormส่วนประกอบหลักคุณก็สามารถใช้@form:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@form" action="#{bean.action}" />
</h:form>

บางครั้งสิ่งนี้อาจไม่พึงประสงค์หากแบบฟอร์มมีส่วนประกอบอินพุตที่คุณต้องการข้ามไปในการประมวลผลมากกว่าบ่อยครั้งในกรณีที่คุณต้องการอัปเดตองค์ประกอบอินพุตอื่นหรือส่วน UI บางส่วนตามองค์ประกอบอินพุตปัจจุบันใน วิธีการฟัง ajax คุณไม่ต้องการให้ข้อผิดพลาดในการตรวจสอบความถูกต้องของส่วนประกอบอินพุตอื่น ๆ ป้องกันไม่ให้เมธอด ajax listener ทำงาน

@allจากนั้นก็มี สิ่งนี้ไม่มีผลพิเศษในprocessแอตทริบิวต์ แต่เฉพาะในupdateแอตทริบิวต์ ทำงานตรงเช่นเดียวกับprocess="@all" process="@form"HTML ไม่สนับสนุนการส่งหลายรูปแบบพร้อมกัน

มีโดยวิธีการนี้ยังมี@noneซึ่งอาจจะเป็นประโยชน์ในกรณีที่คุณอย่างไม่จำเป็นต้องที่จะดำเนินการอะไร แต่เพียงต้องการปรับปรุงชิ้นส่วนบางอย่างผ่านupdateโดยเฉพาะอย่างยิ่งในส่วนผู้ที่มีเนื้อหาไม่ได้ขึ้นอยู่กับค่าส่งหรือฟังการดำเนินการ

ควรสังเกตว่าprocessแอตทริบิวต์นั้นไม่มีผลกับส่วนของคำขอ HTTP (จำนวนพารามิเตอร์คำขอ) ความหมายพฤติกรรม HTML เริ่มต้นของการส่ง "ทุกอย่าง" ที่มีอยู่ภายในการเป็นตัวแทน HTML ของ<h:form>จะไม่ได้รับผลกระทบ ในกรณีที่คุณมีรูปแบบที่มีขนาดใหญ่และต้องการที่จะลดน้ำหนักบรรทุกร้องขอ HTTP เพียงเหล่านี้จำเป็นอย่างยิ่งในการประมวลผลคือเหล่านี้เท่านั้นปกคลุมด้วยprocessแอตทริบิวต์แล้วคุณสามารถตั้งค่าpartialSubmitแอตทริบิวต์ในส่วนประกอบ PrimeFaces อาแจ็กซ์ในขณะที่หรือ<p:commandXxx ... partialSubmit="true"> <p:ajax ... partialSubmit="true">คุณสามารถกำหนดค่านี้ 'ทั่วโลก' โดยแก้ไขweb.xmlและเพิ่ม

<context-param>
    <param-name>primefaces.SUBMIT</param-name>
    <param-value>partial</param-value>
</context-param>

หรือคุณสามารถใช้<o:form>OmniFaces 3.0+ ซึ่งเป็นค่าเริ่มต้นของพฤติกรรมนี้

JSF เทียบเท่ามาตรฐานเพื่อ PrimeFaces เฉพาะprocessคือจากexecute <f:ajax execute>มันทำงานเหมือนกันยกเว้นว่าจะไม่รองรับสตริงที่คั่นด้วยเครื่องหมายจุลภาคในขณะที่ PrimeFaces ทำอยู่ (แม้ว่าโดยส่วนตัวแล้วฉันแนะนำให้ติดกับแบบแผนที่คั่นด้วยช่องว่าง) หรือ@parentคำสำคัญ นอกจากนี้ก็อาจจะเป็นประโยชน์ที่จะรู้ว่า<p:commandXxx process>ค่าเริ่มต้น@formในขณะที่<p:ajax process>และค่าเริ่มต้น<f:ajax execute> @thisในที่สุดมันก็มีประโยชน์ที่จะรู้ว่าprocessสนับสนุนสิ่งที่เรียกว่า "ตัวเลือก PrimeFaces" ดูเพิ่มเติมPrimeFaces Selectors เช่นเดียวกับใน update = "@ (. myClass)" ทำงานอย่างไร?


<p:commandXxx update> <p:ajax update> <f:ajax render>

updateแอตทริบิวต์ด้านลูกค้าและสามารถส่งผลกระทบต่อการแสดง HTML ของทุกUIComponents updateแอตทริบิวต์บอก JavaScript (หนึ่งรับผิดชอบในการจัดการกับอาแจ็กซ์คำขอ / ตอบสนอง) โดยใช้รายการพื้นที่ที่คั่นของรหัสลูกค้าซึ่งส่วนในต้นไม้จำเป็น HTML DOM ได้รับการปรับปรุงเป็นตอบสนองต่อการส่งแบบฟอร์ม

จากนั้น JSF จะจัดเตรียมการตอบสนอง ajax ที่ถูกต้องสำหรับสิ่งนั้นซึ่งมีเฉพาะส่วนที่ร้องขอเพื่ออัปเดต JSF จะข้ามส่วนประกอบอื่น ๆ ทั้งหมดที่ไม่ได้รับการคุ้มครองโดยupdateคุณลักษณะในการตอบสนอง ajax โดยที่นี่จะรักษาอัตราการตอบสนองที่เล็ก นอกจากนี้ส่วนประกอบที่มีแอrenderedททริบิวต์ประเมินfalseระหว่างการตอบสนองการแสดงผลจะถูกข้ามไป โปรดสังเกตว่าแม้ว่ามันจะกลับมาtrue, JavaScript ไม่สามารถอัปเดตในต้นไม้ HTML DOM falseถ้ามันเป็นครั้งแรก คุณต้องปิดมันหรืออัปเดตพาเรนต์แทน ดูเพิ่มเติมปรับปรุงอาแจ็กซ์ / ทำให้ไม่ได้ทำงานในส่วนที่มีการแสดงผลแอตทริบิวต์

โดยปกติแล้วคุณต้องการอัปเดตเพียงส่วนประกอบซึ่งจริงๆจะต้องมีการ "ฟื้นฟู" ในฝั่งไคลเอ็นต์บน (บางส่วน) ส่งแบบฟอร์ม ตัวอย่างด้านล่างอัปเดตฟอร์มหลักทั้งหมดผ่าน@form:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@form" />
</h:form>

(โปรดทราบว่าprocessแอตทริบิวต์นั้นถูกข้ามไปเป็นค่าเริ่มต้น@formแล้ว)

ในขณะที่อาจทำงานได้ดีการอัปเดตคอมโพเนนต์อินพุตและคำสั่งอยู่ในตัวอย่างนี้โดยไม่จำเป็น ถ้าคุณไม่เปลี่ยนแปลงค่ารุ่นfooและวิธีการbarภายในaction(ซึ่งจะไม่ใช้งานง่ายในมุมมองของ UX) จะไม่มีการอัพเดทเลย ส่วนประกอบข้อความเป็นสิ่งเดียวที่จำเป็นต้องได้รับการอัพเดตจริงๆ

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="foo_m bar_m" />
</h:form>

อย่างไรก็ตามนั่นก็น่าเบื่อเมื่อคุณมีหลายคน นั่นเป็นหนึ่งในเหตุผลที่ PrimeFaces Selectors มีอยู่ คอมโพเนนต์ข้อความเหล่านั้นมีในสไตล์ HTML ทั่วไปที่สร้างขึ้นui-messageดังนั้นควรทำสิ่งต่อไปนี้:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@(.ui-message)" />
</h:form>

(โปรดทราบว่าคุณควรเก็บ ID ไว้ในส่วนประกอบข้อความมิฉะนั้น@(...)จะไม่ทำงาน! อีกครั้งโปรดดูPrimeFaces Selectors เช่นเดียวกับใน update = "@ (. myClass)" ทำงานอย่างไรเพื่อดูรายละเอียด)

การ@parentอัปเดตเฉพาะองค์ประกอบหลักซึ่งจะครอบคลุมองค์ประกอบปัจจุบันและพี่น้องทั้งหมดและลูก ๆ ของพวกเขา สิ่งนี้มีประโยชน์มากขึ้นถ้าคุณแยกแบบฟอร์มในกลุ่มที่มีสติด้วยความรับผิดชอบของแต่ละคน การ@thisปรับปรุงเห็นได้ชัดว่าเป็นเพียงองค์ประกอบปัจจุบัน โดยปกติสิ่งนี้จำเป็นเฉพาะเมื่อคุณต้องการเปลี่ยนหนึ่งในแอตทริบิวต์ HTML ของส่วนประกอบในวิธีการดำเนินการ เช่น

<p:commandButton action="#{bean.action}" update="@this" 
    oncomplete="doSomething('#{bean.value}')" />

ลองนึกภาพว่าความoncompleteต้องการที่จะทำงานกับสิ่งvalueที่มีการเปลี่ยนแปลงactionนั้นโครงสร้างนี้จะไม่ทำงานหากองค์ประกอบไม่ได้รับการปรับปรุงด้วยเหตุผลง่ายๆที่oncompleteเป็นส่วนหนึ่งของการสร้าง HTML output (และการแสดงออกของ EL ทั้งหมดในนั้นมีการประเมิน ระหว่างการตอบกลับการแสดงผล)

@allปรับปรุงเอกสารทั้งหมดซึ่งควรจะใช้ด้วยความระมัดระวัง ปกติคุณต้องการใช้ร้องขอ GET จริงสำหรับนี้แทนโดยทั้งการเชื่อมโยงธรรมดา ( <a>หรือ<h:link>) หรือการเปลี่ยนเส้นทางหลังจากที่โพสต์โดยหรือ?faces-redirect=true ExternalContext#redirect()ในลักษณะพิเศษนั้นprocess="@form" update="@all"มีผลเช่นเดียวกับการส่งไม่ใช่ non-ajax (ไม่ใช่บางส่วน) ในอาชีพ JSF ทั้งหมดของฉันกรณีใช้อย่างสมเหตุสมผลเพียงอย่างเดียวที่ฉันพบ@allคือแสดงหน้าข้อผิดพลาดอย่างครบถ้วนในกรณีที่มีข้อยกเว้นเกิดขึ้นระหว่างคำขอ ajax ดูเพิ่มเติมวิธีที่ถูกต้องในการจัดการกับข้อยกเว้น JSF 2.0 สำหรับคอมโพเนนต์ AJAXified คืออะไร

JSF เทียบเท่ามาตรฐานเพื่อ PrimeFaces เฉพาะupdateคือจากrender <f:ajax render>มันทำงานเหมือนกันยกเว้นว่าจะไม่รองรับสตริงที่คั่นด้วยเครื่องหมายจุลภาคในขณะที่ PrimeFaces ทำอยู่ (แม้ว่าโดยส่วนตัวแล้วฉันแนะนำให้ติดกับแบบแผนที่คั่นด้วยช่องว่าง) หรือ@parentคำสำคัญ ทั้งสองupdateและrenderค่าเริ่มต้นเป็น@none(ซึ่งก็คือ "ไม่มีอะไร")


ดูสิ่งนี้ด้วย:


เมื่อฉันใช้ update = "" แล้วคุณสมบัติที่มีการจัดการของ backup bean ไม่ได้รับการตั้งค่าและรูทีน @PostConstruct ของฉันล้มเหลว ความคิดใด ๆ แก้ไข: •หากคุณอาศัยคุณสมบัติที่มีการจัดการของ # {param} ที่มีอยู่ในคำขอ POST ที่ตามมาคุณจะต้องรวมเป็น <f: param> ในคอมโพเนนต์ UICommand
K.Nicholas

อาจกระบวนการ / การปรับปรุงของ panelGroup จะประมวลผล / อัปเดตเนื้อหาของ panelGroup นี้อดีต: <h: panelGroup id = "pgId"> // ตำราป้อนข้อความไปที่นี่ <h: panelGroup> <p: commandLink process = "pgId" = "pgId" />
bob-cac

ขอบคุณ @BalusC สำหรับคำอธิบายที่ดีมากนี้!
ProgrammingIsAwsome

2
@Rapster: เนื่องจากprocessไม่ได้ตั้งค่าดังนั้นจึงใช้ค่าเริ่มต้น@formเป็น นี่คือคำอธิบายข้างต้นด้วย
BalusC

2
@Roland: มันซ่อนปัญหาที่แตกต่างอย่างจริงจังกับแอพ config
BalusC

54

หากคุณมีช่วงเวลาที่ยากลำบากในการจำค่าเริ่มต้น (ฉันรู้ว่าฉันมี ... ) นี่เป็นสารสกัดสั้น ๆ จากคำตอบของ BalusC:

ส่วนประกอบ | ส่ง | รีเฟรช
------------ | --------------- | --------------
f: ajax | ดำเนินการ = "@ this" | ทำให้ = "@ ไม่มี"
p: ajax | กระบวนการ = "@ นี้" | ปรับปรุง = "@ ไม่มี"
p: commandXXX | กระบวนการ = "@ form" | ปรับปรุง = "@ ไม่มี"

เพียงแค่การแก้ไขเล็ก ๆ น้อย ๆ : ค่าเริ่มต้นของprocessสำหรับเป็นp:commandXXX @allนอกจากนี้ดูเหมือนว่าจะนำไปใช้สำหรับองค์ประกอบสนับสนุน AJAX p:menuitemเช่นทุก
เตฟาน Rauh

1
สวัสดี @StephanRauh ขอบคุณมากสำหรับความคิดเห็น คุณอ่านค่าเริ่มต้น@allที่ไหน เท่าที่ฉันสามารถอ่านได้จากคำตอบของ BalusC มันเป็น@formอย่างไร@allจะเทียบเท่ากับ@formในกระบวนการ จุดดีเกี่ยวกับองค์ประกอบอื่น ๆ ฉันคิดว่าฉันจะต้องดูในซอร์สโค้ดเมื่อถึงเวลาที่จะดูว่ามันใช้กับองค์ประกอบใดเพราะฉันไม่อยากเขียนสิ่งที่อาจผิด
Jaqen H'ghar

1
@ JaqenH'ghar Thomas Andraschko บอกเรื่อง@allเล็กน้อย เขาต้องรู้ว่าเขาได้ติดตั้งเอนจิ้น AJAX ของ PrimeFaces อีกครั้งเมื่อเร็ว ๆ นี้ ต่อมาฉันตรวจสอบอีกครั้ง แต่อ่านซอร์สโค้ดของ PrimeFaces และดูที่คำขอ XHR ฉันหวังว่าฉันจะทำให้ถูกต้องในเวลานี้เพราะฉันได้ดำเนินการตามคำขอ AJAX ของ BootsFaces เพื่อทำงานเหมือนกับคำขอ AJAX ของ PrimeFaces
เตฟาน Rauh

มันจะทำให้เข้าใจผิดที่จะบอกว่าเริ่มต้นคือ @ ทั้งหมดเมื่อ HTML ไม่สนับสนุนการส่งหลายรูปแบบ นักพัฒนาจำเป็นต้องรู้ค่าเริ่มต้นที่มีประสิทธิภาพ (ดังนั้นโทมัสอาจเปลี่ยนแปลงได้ตามนั้น) โดยค่าเริ่มต้นเหล่านี้จะถูกกำหนดอย่างไม่ถูกต้องเป็นโมฆะในคู่มือผู้ใช้ Primefaces 6.2
Marc Dzaebel

27

ตามกระบวนการ (ในสเปค JSF เรียกว่าเรียกใช้) คุณบอกให้ JSF จำกัด การประมวลผลไปยังคอมโพเนนต์ที่ระบุทุกสิ่งอื่น ๆ จะถูกละเว้น

อัปเดตระบุองค์ประกอบที่จะอัปเดตเมื่อเซิร์ฟเวอร์ตอบกลับไปที่คุณร้องขอ

@ ทั้งหมด : ทุกองค์ประกอบจะถูกประมวลผล / แสดงผล

@this : องค์ประกอบที่ร้องขอพร้อมกับคุณสมบัติ execute ถูกประมวลผล / แสดงผล

@form : แบบฟอร์มที่มีองค์ประกอบที่ร้องขอจะถูกประมวลผล / แสดงผล

@parent : ผู้ปกครองที่มีองค์ประกอบที่ร้องขอมีการประมวลผล / แสดงผล

ด้วย Primefaces คุณยังสามารถใช้ตัวเลือก JQuery ลองดูที่บล็อกนี้: http://blog.primefaces.org/?p=1867


2

โปรดทราบว่า PrimeFaces รองรับคำหลักมาตรฐาน JSF 2.0+:

  • @this องค์ประกอบปัจจุบัน
  • @all มุมมองทั้งหมด
  • @form รูปแบบบรรพบุรุษที่ใกล้ที่สุดขององค์ประกอบปัจจุบัน
  • @none ไม่มีส่วนประกอบ

และคำหลักมาตรฐาน JSF 2.3+:

  • @child(n) เด็กคนที่
  • @composite บรรพบุรุษของส่วนประกอบคอมโพสิตที่ใกล้ที่สุด
  • @id(id) ใช้เพื่อค้นหาส่วนประกอบโดยใช้ ID โดยไม่สนใจโครงสร้างโครงสร้างส่วนประกอบและการตั้งชื่อคอนเทนเนอร์
  • @namingcontainer ภาชนะตั้งชื่อบรรพบุรุษที่ใกล้เคียงที่สุดขององค์ประกอบปัจจุบัน
  • @parent พาเรนต์ขององค์ประกอบปัจจุบัน
  • @previous พี่น้องก่อนหน้า
  • @next พี่น้องคนต่อไป
  • @root อินสแตนซ์ของมุมมอง UIViewRoot สามารถใช้เพื่อเริ่มการค้นหาจากรูทแทนองค์ประกอบปัจจุบัน

แต่มันยังมาพร้อมกับคำหลักเฉพาะ PrimeFaces:

  • @row(n) แถวที่
  • @widgetVar(name) ส่วนประกอบที่มี widgetVar ที่กำหนด

และคุณสามารถใช้สิ่งที่เรียกว่า "PrimeFaces Selectors" ซึ่งอนุญาตให้คุณใช้ jQuery Selector API ตัวอย่างเช่นการประมวลผลอินพุตทั้งหมดในองค์ประกอบด้วยคลาส CSS myClass:

process="@(.myClass :input)"

ดู:


2
โปรดทราบว่าแม้ JSF2.3 + สนับสนุนคำหลักส่วนใหญ่
tandraschko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.