| CODENOTIFIER | HelpYou are not signed inSign in |
Project: erlyweb
Revision: 221
Author: yarivvv
Date: 27 Dec 2007 02:50:37
Changes:documentation changes
Files:| ... | ...@@ -458,28 +458,60 @@ | |
| 458 | 458 | |
| 459 | 459 | In ErlyWeb 0.5, the `phased' return type for hook/1 was introduced to let you |
| 460 | 460 | embed components in containers after those components are rendered |
| 461 | but before they are sent to the browser | |
| 461 | but before the result of the rendering is sent to the browser | |
| 462 | 462 | (before ErlyWeb 0.5, a similar but weaker functionality was provided by |
| 463 | app views, which ErlyWeb no longer supports). By returning | |
| 464 | `{phased, Ewc, Fun}', you instruct ErlyWeb to first render the | |
| 463 | app views, which ErlyWeb no longer supports). The most common use for this | |
| 464 | feature is to make ErlyWeb render different components | |
| 465 | with the same outer layout (header, footer, and/or sidebars). | |
| 466 | ||
| 467 | The reason this is feature called 'phased rendering' is that it makes | |
| 468 | ErlyWeb render the response in two phases: first, | |
| 469 | the requested component, and second, the container in which the | |
| 470 | component should be embedded. | |
| 471 | ||
| 472 | The benefits of phased rendering are: | |
| 473 | ||
| 474 | <ul> | |
| 475 | <li>The second phase is only executed if the first phase returns a rendered | |
| 476 | iolist. If the controller function from the first phase returns just | |
| 477 | headers (this frequently happens on redirects), | |
| 478 | ErlyWeb doesn't waste resources rendering any headers and footers.</li> | |
| 479 | <li>The components are ignorant of the containers in which they are embedded. | |
| 480 | This introduces fewer dependencies into the components' code and hence | |
| 481 | makes them more reusable and modular.</li> | |
| 482 | <li>The hook/1 function can use arbitrary logic to decide which component to | |
| 483 | render in the second phase based on the request data and the value returned | |
| 484 | by the controller function in PhasedVars (there will be more on that soon). | |
| 485 | This high degree of granularity allows you, for example, to disable headers | |
| 486 | and footers when rendering the response for an AJAX request as opposed to | |
| 487 | a regular page load, or to tell ErlyWeb to different layouts for | |
| 488 | different component requests.</li> | |
| 489 | </ul> | |
| 490 | ||
| 491 | To use phased rendering, you should return a tuple of the form | |
| 492 | `{phased, Ewc, Fun}' from hook/1. This return value instructs | |
| 493 | ErlyWeb to first render the | |
| 465 | 494 | requested component, and if the result includes a rendered |
| 466 | iolist (i.e., the requested component didn't return only headers), | |
| 467 | then pass it to the function Fun, which would decide if/how the iolist should | |
| 468 | be embedded in a container. | |
| 469 | ||
| 470 | The reason this is feature called 'phased' rendering is that ErlyWeb renders | |
| 471 | the response in 2 phases: first, the requested component, and second, the | |
| 472 | container in which the component should be embedded. | |
| 495 | iolist (i.e., the requested component returned a body and not just headers) | |
| 496 | then pass the iolist to the function Fun. | |
| 473 | 497 | |
| 474 | 498 | Fun takes 3 parameters: the fully expanded 'ewc' tuple |
| 475 | 499 | that ErlyWeb has rendered (this is usually the result of calling |
| 476 | erlyweb:get_initial_ewc({ewc, A})), the rendered | |
| 477 | iolist, and an opaque parameter called 'PhasedVars' ('PhasedVars' was | |
| 478 | introduced in ErlyWeb 0.7). PhasedVars is a list of values returned from | |
| 500 | `erlyweb:get_initial_ewc({ewc, A})'), the rendered | |
| 501 | iolist, and an opaque parameter called 'PhasedVars' (PhasedVars was | |
| 502 | introduced in ErlyWeb 0.7). Through its return value, Fun can tell | |
| 503 | ErlyWeb to pass the iolist as a parameter to the container component | |
| 504 | function that will be used in the second rendering phase. | |
| 505 | ||
| 506 | PhasedVars is a list of values returned from | |
| 479 | 507 | the rendered controller function, in a special tuple of the type |
| 480 | {phased_vars, Vars}. The purpose of 'PhasedVars' is to let the controller | |
| 481 | function pass arbitrary values to the component that | |
| 482 | is rendered in the second phase. It is useful, for example, for letting | |
| 508 | `{phased_vars, Vars}' (an example is shown below). This tuple should be | |
| 509 | included in the Elems list of the `{response, Elems}' tuple that controller | |
| 510 | functions may return (see the section {@section Returning Arbitrary YAWS Tuples} for more info). | |
| 511 | ||
| 512 | The purpose of 'PhasedVars' is to let the controller | |
| 513 | function parameterize the component that is rendered in the second phase. | |
| 514 | It is useful, for example, for letting | |
| 483 | 515 | the controller function set the title of a page when the page's header |
| 484 | 516 | is rendered by the container in the second rendering phase. |
| 485 | 517 | |
| ... | ...@@ -492,13 +524,13 @@ | |
| 492 | 524 | {phased, {ewc, A}, fun(_Ewc, Data, _PhasedVars) -> {data, Data} end} |
| 493 | 525 | ''' |
| 494 | 526 | |
| 495 | It is tantamount to returning | |
| 527 | It is equivalent to returning | |
| 496 | 528 | |
| 497 | 529 | ``` |
| 498 | 530 | {ewc, A} |
| 499 | 531 | ''' |
| 500 | 532 | |
| 501 | This return value tells ErlyWeb to render the component | |
| 533 | Both return values tells ErlyWeb to render the component | |
| 502 | 534 | that corresponds to the arg's appmoddata field, and then return |
| 503 | 535 | the rendered iolist to the browser verbatim. |
| 504 | 536 | |
| ... | ...@@ -513,12 +545,13 @@ | |
| 513 | 545 | ''' |
| 514 | 546 | |
| 515 | 547 | This return value tells ErlyWeb to first render the component that corresponds |
| 516 | to the arg's appmoddata field, and then embed the rendered iolist | |
| 517 | (the 'Data' variable) in html_container. After ErlyWeb renders | |
| 518 | the requested component, it calls | |
| 519 | `html_container_controller:index(A, {data, Data}, proplists:get_value(title, PhasedVars))' and passes the result to html_container_view:index/1. | |
| 548 | to the arg's appmoddata field, and then pass the rendered iolist | |
| 549 | (the 'Data' variable) as the second parameter to | |
| 550 | html_container_controller:index/3. The third parameter is the 'title' property | |
| 551 | that may exist in the PhasedVars property list, or 'undefined' if the 'title' | |
| 552 | property doesn't exist. | |
| 520 | 553 | |
| 521 | How do you set the value of the 'title' property in PhasedVars? Below is | |
| 554 | How do you set the value of PhasedVars? Below is | |
| 522 | 555 | an example controller function for an 'album' component that fetches from |
| 523 | 556 | the database an album and its related songs, passes the song names to the |
| 524 | 557 | view function, and sets the page's title according to the album name. |
| ... | ...@@ -535,9 +568,13 @@ | |
| 535 | 568 | {body, {data, [{song:name(S) || S <- Songs}]}}]}. |
| 536 | 569 | ''' |
| 537 | 570 | |
| 538 | Finally, below is an example html_container that takes the iolist and the | |
| 539 | 'title' parameter and inserts them into the proper positions in the HTML | |
| 540 | page. | |
| 571 | This code snippet exemplifies how a controller function can tell ErlyWeb | |
| 572 | both what data to pass to the view function as well as the value of the | |
| 573 | PhasedVars parameter that will be passed to Fun in the second rendering phase. | |
| 574 | ||
| 575 | Finally, below is an example html_container component that takes the rendered | |
| 576 | iolist and the 'title' parameter and inserts them into the proper positions | |
| 577 | in the HTML page. | |
| 541 | 578 | |
| 542 | 579 | html_container_controller.erl: |
| 543 | 580 |
| ... | ...@@ -431,28 +431,60 @@ | |
| 431 | 431 | |
| 432 | 432 | <p>In ErlyWeb 0.5, the <code>phased</code> return type for hook/1 was introduced to let you |
| 433 | 433 | embed components in containers after those components are rendered |
| 434 | but before they are sent to the browser | |
| 434 | but before the result of the rendering is sent to the browser | |
| 435 | 435 | (before ErlyWeb 0.5, a similar but weaker functionality was provided by |
| 436 | app views, which ErlyWeb no longer supports). By returning | |
| 437 | <code>{phased, Ewc, Fun}</code>, you instruct ErlyWeb to first render the | |
| 436 | app views, which ErlyWeb no longer supports). The most common use for this | |
| 437 | feature is to make ErlyWeb render different components | |
| 438 | with the same outer layout (header, footer, and/or sidebars).</p> | |
| 439 | ||
| 440 | <p>The reason this is feature called 'phased rendering' is that it makes | |
| 441 | ErlyWeb render the response in two phases: first, | |
| 442 | the requested component, and second, the container in which the | |
| 443 | component should be embedded.</p> | |
| 444 | ||
| 445 | <p>The benefits of phased rendering are:</p> | |
| 446 | ||
| 447 | <ul> | |
| 448 | <li>The second phase is only executed if the first phase returns a rendered | |
| 449 | iolist. If the controller function from the first phase returns just | |
| 450 | headers (this frequently happens on redirects), | |
| 451 | ErlyWeb doesn't waste resources rendering any headers and footers.</li> | |
| 452 | <li>The components are ignorant of the containers in which they are embedded. | |
| 453 | This introduces fewer dependencies into the components' code and hence | |
| 454 | makes them more reusable and modular.</li> | |
| 455 | <li>The hook/1 function can use arbitrary logic to decide which component to | |
| 456 | render in the second phase based on the request data and the value returned | |
| 457 | by the controller function in PhasedVars (there will be more on that soon). | |
| 458 | This high degree of granularity allows you, for example, to disable headers | |
| 459 | and footers when rendering the response for an AJAX request as opposed to | |
| 460 | a regular page load, or to tell ErlyWeb to different layouts for | |
| 461 | different component requests.</li> | |
| 462 | </ul> | |
| 463 | ||
| 464 | <p>To use phased rendering, you should return a tuple of the form | |
| 465 | <code>{phased, Ewc, Fun}</code> from hook/1. This return value instructs | |
| 466 | ErlyWeb to first render the | |
| 438 | 467 | requested component, and if the result includes a rendered |
| 439 | iolist (i.e., the requested component didn't return only headers), | |
| 440 | then pass it to the function Fun, which would decide if/how the iolist should | |
| 441 | be embedded in a container.</p> | |
| 442 | ||
| 443 | <p>The reason this is feature called 'phased' rendering is that ErlyWeb renders | |
| 444 | the response in 2 phases: first, the requested component, and second, the | |
| 445 | container in which the component should be embedded.</p> | |
| 468 | iolist (i.e., the requested component returned a body and not just headers) | |
| 469 | then pass the iolist to the function Fun.</p> | |
| 446 | 470 | |
| 447 | 471 | <p>Fun takes 3 parameters: the fully expanded 'ewc' tuple |
| 448 | 472 | that ErlyWeb has rendered (this is usually the result of calling |
| 449 | erlyweb:get_initial_ewc({ewc, A})), the rendered | |
| 450 | iolist, and an opaque parameter called 'PhasedVars' ('PhasedVars' was | |
| 451 | introduced in ErlyWeb 0.7). PhasedVars is a list of values returned from | |
| 473 | <code>erlyweb:get_initial_ewc({ewc, A})</code>), the rendered | |
| 474 | iolist, and an opaque parameter called 'PhasedVars' (PhasedVars was | |
| 475 | introduced in ErlyWeb 0.7). Through its return value, Fun can tell | |
| 476 | ErlyWeb to pass the iolist as a parameter to the container component | |
| 477 | function that will be used in the second rendering phase.</p> | |
| 478 | ||
| 479 | <p>PhasedVars is a list of values returned from | |
| 452 | 480 | the rendered controller function, in a special tuple of the type |
| 453 | {phased_vars, Vars}. The purpose of 'PhasedVars' is to let the controller | |
| 454 | function pass arbitrary values to the component that | |
| 455 | is rendered in the second phase. It is useful, for example, for letting | |
| 481 | <code>{phased_vars, Vars}</code> (an example is shown below). This tuple should be | |
| 482 | included in the Elems list of the <code>{response, Elems}</code> tuple that controller | |
| 483 | functions may return (see the section <a href="#Returning_Arbitrary_YAWS_Tuples">Returning Arbitrary YAWS Tuples</a> for more info).</p> | |
| 484 | ||
| 485 | <p>The purpose of 'PhasedVars' is to let the controller | |
| 486 | function parameterize the component that is rendered in the second phase. | |
| 487 | It is useful, for example, for letting | |
| 456 | 488 | the controller function set the title of a page when the page's header |
| 457 | 489 | is rendered by the container in the second rendering phase.</p> |
| 458 | 490 | |
| ... | ...@@ -463,11 +495,11 @@ | |
| 463 | 495 | |
| 464 | 496 | <pre>{phased, {ewc, A}, fun(_Ewc, Data, _PhasedVars) -> {data, Data} end}</pre> |
| 465 | 497 | |
| 466 | <p>It is tantamount to returning</p> | |
| 498 | <p>It is equivalent to returning</p> | |
| 467 | 499 | |
| 468 | 500 | <pre>{ewc, A}</pre> |
| 469 | 501 | |
| 470 | <p>This return value tells ErlyWeb to render the component | |
| 502 | <p>Both return values tells ErlyWeb to render the component | |
| 471 | 503 | that corresponds to the arg's appmoddata field, and then return |
| 472 | 504 | the rendered iolist to the browser verbatim.</p> |
| 473 | 505 | |
| ... | ...@@ -480,12 +512,13 @@ | |
| 480 | 512 | end}</pre> |
| 481 | 513 | |
| 482 | 514 | <p>This return value tells ErlyWeb to first render the component that corresponds |
| 483 | to the arg's appmoddata field, and then embed the rendered iolist | |
| 484 | (the 'Data' variable) in html_container. After ErlyWeb renders | |
| 485 | the requested component, it calls | |
| 486 | <code>html_container_controller:index(A, {data, Data}, proplists:get_value(title, PhasedVars))</code> and passes the result to html_container_view:index/1.</p> | |
| 515 | to the arg's appmoddata field, and then pass the rendered iolist | |
| 516 | (the 'Data' variable) as the second parameter to | |
| 517 | html_container_controller:index/3. The third parameter is the 'title' property | |
| 518 | that may exist in the PhasedVars property list, or 'undefined' if the 'title' | |
| 519 | property doesn't exist.</p> | |
| 487 | 520 | |
| 488 | <p>How do you set the value of the 'title' property in PhasedVars? Below is | |
| 521 | <p>How do you set the value of PhasedVars? Below is | |
| 489 | 522 | an example controller function for an 'album' component that fetches from |
| 490 | 523 | the database an album and its related songs, passes the song names to the |
| 491 | 524 | view function, and sets the page's title according to the album name.</p> |
| ... | ...@@ -500,9 +533,13 @@ | |
| 500 | 533 | [{phased_vars, [{title, [<<"song list for ">>, AlbumName]}]}, |
| 501 | 534 | {body, {data, [{song:name(S) || S <- Songs}]}}]}.</pre> |
| 502 | 535 | |
| 503 | <p>Finally, below is an example html_container that takes the iolist and the | |
| 504 | 'title' parameter and inserts them into the proper positions in the HTML | |
| 505 | page.</p> | |
| 536 | <p>This code snippet exemplifies how a controller function can tell ErlyWeb | |
| 537 | both what data to pass to the view function as well as the value of the | |
| 538 | PhasedVars parameter that will be passed to Fun in the second rendering phase.</p> | |
| 539 | ||
| 540 | <p>Finally, below is an example html_container component that takes the rendered | |
| 541 | iolist and the 'title' parameter and inserts them into the proper positions | |
| 542 | in the HTML page.</p> | |
| 506 | 543 | |
| 507 | 544 | <p>html_container_controller.erl:</p> |
| 508 | 545 |