{"__v":2,"_id":"55097b272dd6a11900e6e7bb","category":{"__v":8,"_id":"550974cc368a56170041475d","project":"55070e814bb83b2500ec9404","version":"550974cb368a561700414757","pages":["55097b214c7c3f2300aabf0f","55097b272dd6a11900e6e7bb","55097b2edd77250d00736a09","55097b352dd6a11900e6e7c2","55097b3e2dd6a11900e6e7c6","55097b4e4c7c3f2300aabf12","55097b712dd6a11900e6e7c8","55097b8bad1f0523008ecbdc"],"reference":false,"createdAt":"2015-03-18T11:08:31.853Z","from_sync":false,"order":4,"slug":"displaying-views-to-users","title":"Displaying Views to Users"},"project":"55070e814bb83b2500ec9404","user":"55070d24d30b3f190011b941","version":{"__v":1,"_id":"550974cb368a561700414757","forked_from":"55070e814bb83b2500ec9407","project":"55070e814bb83b2500ec9404","createdAt":"2015-03-18T12:51:23.709Z","releaseDate":"2015-03-18T12:51:23.709Z","categories":["550974cc368a561700414758","550974cc368a561700414759","550974cc368a56170041475a","550974cc368a56170041475b","550974cc368a56170041475c","550974cc368a56170041475d","550974cc368a56170041475e"],"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.4.0","version":"1.4"},"updates":[],"createdAt":"2015-03-18T13:18:31.825Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"auth":"required","params":[],"url":""},"order":1,"body":"Partials in Wheels act as a wrapper around the good old `<cfinclude>` tag. By calling [includePartial()](doc:includepartial) or [renderPartial()](doc:renderpartial), you can include other view files in a page, just like `<cfinclude>` would. But at the same time, partials make use of common Wheels features like layouts, caching, model objects, and so on.\n\nThese functions also add a few cool things to your development arsenal like the ability to pass in a query or array of objects and have the partial file called on each iteration (to name one).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Why Use a Partial?\"\n}\n[/block]\nWebsites often display the same thing on multiple pages. It could be an advertisement area that should be displayed in an entire section of a website or a shopping cart that is displayed while browsing products in a shop. You get the idea. To avoid duplicating code, you can place it in a file (the \"partial\" in Wheels terms) and include that file using [includePartial()](doc:includepartial) on the pages that need it.\n\nEven when there is no risk of code duplication, it can still make sense to use a partial. Breaking up a large page into smaller, more manageable chunks will help you focus on each part individually.\n\nIf you've used `<cfinclude>` a lot in the past (and who hasn't?!), you probably already knew all of this though, right?\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Storing Your Partial Files\"\n}\n[/block]\nTo make it clear that a file is a partial and not a full page, we start the filename with an underscore character. You can place the partial file anywhere in the `views` folder. When locating partials, Wheels will use the same rules as it does for the `template` argument to [renderPage()](doc:renderpage). This means that if you save the partial in the current controller's view folder, you reference it simply by its name.\n\nFor example, if you wanted to have a partial for a comment in your `blog` controller, you would save the file at `views/blog/_comment.cfm` and reference it (in [includePartial()](doc:includepartial) and [renderPartial()](doc:renderpartial)) with just \"`comment`\" as the first argument.\n\nSometimes it's useful to share partials between controllers though. Perhaps you have a banner ad that should be displayed across several controllers. One common approach then is to save them in a dedicated folder for this at the root of the `views` folder. To reference partials in this folder, in this case named shared, you would then pass in `\"/shared/banner\"` to [includePartial()](doc:includepartial) instead.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Making the Call\"\n}\n[/block]\nNow that we know why we should use partials and where to store them, let's make a call to [includePartial()](doc:includepartial) from a view page to have Wheels display a partial's output.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfoutput>#includePartial(\\\"banner\\\")#</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nThat code will look for a file named `_banner.cfm` in the current controller's view folder and include it.\n\nLet's say we're in the `blog` controller. Then the file that will be included is `views/blog/_banner.cfm`.\n\nAs you can see, you don't need to specify the `.cfm` part or the underscore when referencing a partial.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Passing in Data\"\n}\n[/block]\nYou can pass in data by adding named arguments on the [includePartial()](doc:includepartial) call. Because we use the `partial` argument to determine what file to include, you can't pass in a variable named partial though. The same goes for the other arguments as well, like `layout`, `spacer`, and `cache`.\n\nHere is an example of passing in a title to a partial for a form:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfoutput>\\n#includePartial(partial=\\\"loginRegisterForm\\\", title=\\\"Please log in here\\\")#\\n</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nNow you can reference the title variable as `arguments.title` inside the `_loginregisterform.cfm` file.\n\nIf you prefer, you can still access the view variables that are set outside of the partial. The advantage with specifically passing them in instead is that they are then scoped in the `arguments` struct (which means less chance of strange bugs occurring due to variable conflicts). It also makes for more readable and maintainable code. (You can see the intent of the partial better when you see what is passed in to it).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Automatic Calls to a Data Function\"\n}\n[/block]\nThere is an even more elegant way of passing data to a partial though. When you start using a partial on several pages on a site spread across multiple controllers, it can get quite cumbersome to remember to first load the data in an appropriate function in the controller, setup a before filter for it, pass that data in to the partial, and so on.\n\nWheels can automate this process for you. The convention is that a partial will always check if a function exists on the controller with the same name as the partial itself (and that it's set to `private` and will return a struct). If so, the partial will call the function and add the output returned to its `arguments` struct.\n\nThis way, the partial can be called from anywhere and acts more like a \"black box.\" All communication with the model is kept in the controller as it should be for example.\n\nIf you don't want to load the data from a function with the same name as the partial (perhaps due to it clashing with another function name), you can specify the function to load data from with the `dataFunction` argument to [includePartial()](doc:includepartial) and [renderPartial()](doc:renderpartial).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Partials with Layouts\"\n}\n[/block]\nJust like a regular page, Wheels partials also understand the concept of layouts. To use this feature, simply pass in the name of the layout file you want to wrap the partial in with the `layout` argument, like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfoutput>\\n#includePartial(partial=\\\"newsItem\\\", layout=\\\"/boxes/blue\\\")#\\n</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nThis will wrap the partial with the code found in `views/boxes/_blue.cfm`. Just like with other layouts, you use [includeContent()](doc:includecontent) to represent the partial's content.\n\nThat said, your `_blue.cfm` file could end up looking something like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<div class=\\\"news\\\">\\n    <cfoutput>#includeContent()#</cfoutput>\\n</div>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nOne difference from page layouts is that the layout file for partials has to start with the underscore character.\n\nIt's also worth noting that it's perfectly acceptable to include partials inside layout files as well. This opens up the possibility to nest layouts in complex ways.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Caching a Partial\"\n}\n[/block]\nCaching a partial is done the same way as caching a page. Pass in the number of minutes you want to cache the partial for to the `cache` argument.\n\nHere's an example where we cache a partial for 15 minutes:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfoutput>\\n#includePartial(partial=\\\"userListing\\\", cache=15)#\\n</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Partials with an Object\"\n}\n[/block]\nBecause it's quite common to use partials in conjunction with objects and queries, Wheels has built-in support for this too. Have a look at the code below, which passes in an object to a partial:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfset cust = model(\\\"customer\\\").findByKey(params.key)>\\n<cfoutput>#includePartial(cust)#</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nThat code will figure out that the `cust` variable contains a `customer` model object. It will then try to include a partial named `_customer.cfm` and pass in the object's properties as arguments to the partial. There will also be an `object` variable available in the `arguments` struct if you prefer to reference the object directly.\n\nTry that code and `<cfdump>` the `arguments` struct inside the partial file, and you'll see what's going on. Pretty cool stuff, huh?\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Partials with a Query\"\n}\n[/block]\nSimilar to passing in an object, you can also pass in a query result set to [includePartial()](doc:includepartial). Here's how that looks:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfset customers = model(\\\"customer\\\").findAll()>\\n<cfoutput>#includePartial(customers)#</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nIn this case, Wheels will iterate through the query and call the `_customer.cfm` partial on each iteration. Similar to the example with the object above, Wheels will pass in the objects' properties (in this case represented by records in the query) to the partial.\n\nIn addition to that, you will also see that a counter variable is available. It's named `current` and is available when passing in queries or arrays of objects to a partial.\n\nThe way partials handle objects and queries makes it possible to use the exact same code inside the partial regardless of whether we're dealing with an object or query record at the time.\n\nIf you need to display some HTML in between each iteration (maybe each iteration should be a list item for example), then you can make use of the `spacer` argument. Anything passed in to that will be inserted between iterations. Here's an example:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfoutput>\\n\\n<ul>\\n    <li>#includePartial(partial=customers, spacer=\\\"</li><li>\\\")#</li>\\n</ul>\\n\\n</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Partials and Grouping\"\n}\n[/block]\nThere is a feature of CFML that is very handy: the ability to output a query with the group attribute. Here's an example of how this can be done with a query that contains artists and albums (with the artist potentially being duplicated since they can have more than one album):\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfoutput query=\\\"artistsAndAlbums\\\" group=\\\"artistid\\\">\\n    <!--- Artist info is displayed just once for each artist here --->\\n    <cfoutput>\\n        <!--- Each album is looped here --->\\n    </cfoutput>\\n</cfoutput>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nWe have ported this great functionality into calling partials with queries as well. Here's how you can achieve it:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#includePartial(partial=artistsAndAlbums, group=\\\"artistId\\\")#\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nWhen inside the partial file, you'll have an additional subquery made available to you named `group`, which contains the albums for the current artist in the loop.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Partials with an Array of Objects\"\n}\n[/block]\nAs we've hinted previously in this chapter, it's also possible to pass in an array of objects to a partial. It works very similar to passing in a query in that the partial is called on each iteration.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Rendering or Including?\"\n}\n[/block]\nSo far we've only talked about [includePartial()](doc:includepartial), which is what you use from within your views to include other files. There is another similar function as well: [renderPartial()](doc:renderpartial). This one is used from your controller files when you want to render a partial instead of a full page. At first glance, this might not make much sense to do. There is one common usage of this though—AJAX requests.\n\nLet's say that you want to submit comments on your blog using AJAX. For example, the user will see all comments, enter their comment, submit it, and the comment will show up below the existing ones without a new page being loaded.\n\nIn this case, it's useful to use a partial to display each comment (using [includePartial()](doc:includepartial) as outlined above) and use the same partial when rendering the result of the AJAX request.\n\nHere's what your controller action that receives the AJAX form submission would look like:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<cfset comment = model(\\\"comment\\\").create(params.newComment)>\\n<cfset renderPartial(comment)>\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nPlease note that there currently is no support for creating the AJAX form directly with Wheels. This can easily be implemented using a JavaScript library such as jQuery or Prototype though.","excerpt":"Simplify your views by breaking them down into partial page templates.","slug":"partials","type":"basic","title":"Partials"}

Partials

Simplify your views by breaking them down into partial page templates.

Partials in Wheels act as a wrapper around the good old `<cfinclude>` tag. By calling [includePartial()](doc:includepartial) or [renderPartial()](doc:renderpartial), you can include other view files in a page, just like `<cfinclude>` would. But at the same time, partials make use of common Wheels features like layouts, caching, model objects, and so on. These functions also add a few cool things to your development arsenal like the ability to pass in a query or array of objects and have the partial file called on each iteration (to name one). [block:api-header] { "type": "basic", "title": "Why Use a Partial?" } [/block] Websites often display the same thing on multiple pages. It could be an advertisement area that should be displayed in an entire section of a website or a shopping cart that is displayed while browsing products in a shop. You get the idea. To avoid duplicating code, you can place it in a file (the "partial" in Wheels terms) and include that file using [includePartial()](doc:includepartial) on the pages that need it. Even when there is no risk of code duplication, it can still make sense to use a partial. Breaking up a large page into smaller, more manageable chunks will help you focus on each part individually. If you've used `<cfinclude>` a lot in the past (and who hasn't?!), you probably already knew all of this though, right? [block:api-header] { "type": "basic", "title": "Storing Your Partial Files" } [/block] To make it clear that a file is a partial and not a full page, we start the filename with an underscore character. You can place the partial file anywhere in the `views` folder. When locating partials, Wheels will use the same rules as it does for the `template` argument to [renderPage()](doc:renderpage). This means that if you save the partial in the current controller's view folder, you reference it simply by its name. For example, if you wanted to have a partial for a comment in your `blog` controller, you would save the file at `views/blog/_comment.cfm` and reference it (in [includePartial()](doc:includepartial) and [renderPartial()](doc:renderpartial)) with just "`comment`" as the first argument. Sometimes it's useful to share partials between controllers though. Perhaps you have a banner ad that should be displayed across several controllers. One common approach then is to save them in a dedicated folder for this at the root of the `views` folder. To reference partials in this folder, in this case named shared, you would then pass in `"/shared/banner"` to [includePartial()](doc:includepartial) instead. [block:api-header] { "type": "basic", "title": "Making the Call" } [/block] Now that we know why we should use partials and where to store them, let's make a call to [includePartial()](doc:includepartial) from a view page to have Wheels display a partial's output. [block:code] { "codes": [ { "code": "<cfoutput>#includePartial(\"banner\")#</cfoutput>", "language": "text" } ] } [/block] That code will look for a file named `_banner.cfm` in the current controller's view folder and include it. Let's say we're in the `blog` controller. Then the file that will be included is `views/blog/_banner.cfm`. As you can see, you don't need to specify the `.cfm` part or the underscore when referencing a partial. [block:api-header] { "type": "basic", "title": "Passing in Data" } [/block] You can pass in data by adding named arguments on the [includePartial()](doc:includepartial) call. Because we use the `partial` argument to determine what file to include, you can't pass in a variable named partial though. The same goes for the other arguments as well, like `layout`, `spacer`, and `cache`. Here is an example of passing in a title to a partial for a form: [block:code] { "codes": [ { "code": "<cfoutput>\n#includePartial(partial=\"loginRegisterForm\", title=\"Please log in here\")#\n</cfoutput>", "language": "text" } ] } [/block] Now you can reference the title variable as `arguments.title` inside the `_loginregisterform.cfm` file. If you prefer, you can still access the view variables that are set outside of the partial. The advantage with specifically passing them in instead is that they are then scoped in the `arguments` struct (which means less chance of strange bugs occurring due to variable conflicts). It also makes for more readable and maintainable code. (You can see the intent of the partial better when you see what is passed in to it). [block:api-header] { "type": "basic", "title": "Automatic Calls to a Data Function" } [/block] There is an even more elegant way of passing data to a partial though. When you start using a partial on several pages on a site spread across multiple controllers, it can get quite cumbersome to remember to first load the data in an appropriate function in the controller, setup a before filter for it, pass that data in to the partial, and so on. Wheels can automate this process for you. The convention is that a partial will always check if a function exists on the controller with the same name as the partial itself (and that it's set to `private` and will return a struct). If so, the partial will call the function and add the output returned to its `arguments` struct. This way, the partial can be called from anywhere and acts more like a "black box." All communication with the model is kept in the controller as it should be for example. If you don't want to load the data from a function with the same name as the partial (perhaps due to it clashing with another function name), you can specify the function to load data from with the `dataFunction` argument to [includePartial()](doc:includepartial) and [renderPartial()](doc:renderpartial). [block:api-header] { "type": "basic", "title": "Partials with Layouts" } [/block] Just like a regular page, Wheels partials also understand the concept of layouts. To use this feature, simply pass in the name of the layout file you want to wrap the partial in with the `layout` argument, like this: [block:code] { "codes": [ { "code": "<cfoutput>\n#includePartial(partial=\"newsItem\", layout=\"/boxes/blue\")#\n</cfoutput>", "language": "text" } ] } [/block] This will wrap the partial with the code found in `views/boxes/_blue.cfm`. Just like with other layouts, you use [includeContent()](doc:includecontent) to represent the partial's content. That said, your `_blue.cfm` file could end up looking something like this: [block:code] { "codes": [ { "code": "<div class=\"news\">\n <cfoutput>#includeContent()#</cfoutput>\n</div>", "language": "text" } ] } [/block] One difference from page layouts is that the layout file for partials has to start with the underscore character. It's also worth noting that it's perfectly acceptable to include partials inside layout files as well. This opens up the possibility to nest layouts in complex ways. [block:api-header] { "type": "basic", "title": "Caching a Partial" } [/block] Caching a partial is done the same way as caching a page. Pass in the number of minutes you want to cache the partial for to the `cache` argument. Here's an example where we cache a partial for 15 minutes: [block:code] { "codes": [ { "code": "<cfoutput>\n#includePartial(partial=\"userListing\", cache=15)#\n</cfoutput>", "language": "text" } ] } [/block] [block:api-header] { "type": "basic", "title": "Using Partials with an Object" } [/block] Because it's quite common to use partials in conjunction with objects and queries, Wheels has built-in support for this too. Have a look at the code below, which passes in an object to a partial: [block:code] { "codes": [ { "code": "<cfset cust = model(\"customer\").findByKey(params.key)>\n<cfoutput>#includePartial(cust)#</cfoutput>", "language": "text" } ] } [/block] That code will figure out that the `cust` variable contains a `customer` model object. It will then try to include a partial named `_customer.cfm` and pass in the object's properties as arguments to the partial. There will also be an `object` variable available in the `arguments` struct if you prefer to reference the object directly. Try that code and `<cfdump>` the `arguments` struct inside the partial file, and you'll see what's going on. Pretty cool stuff, huh? [block:api-header] { "type": "basic", "title": "Using Partials with a Query" } [/block] Similar to passing in an object, you can also pass in a query result set to [includePartial()](doc:includepartial). Here's how that looks: [block:code] { "codes": [ { "code": "<cfset customers = model(\"customer\").findAll()>\n<cfoutput>#includePartial(customers)#</cfoutput>", "language": "text" } ] } [/block] In this case, Wheels will iterate through the query and call the `_customer.cfm` partial on each iteration. Similar to the example with the object above, Wheels will pass in the objects' properties (in this case represented by records in the query) to the partial. In addition to that, you will also see that a counter variable is available. It's named `current` and is available when passing in queries or arrays of objects to a partial. The way partials handle objects and queries makes it possible to use the exact same code inside the partial regardless of whether we're dealing with an object or query record at the time. If you need to display some HTML in between each iteration (maybe each iteration should be a list item for example), then you can make use of the `spacer` argument. Anything passed in to that will be inserted between iterations. Here's an example: [block:code] { "codes": [ { "code": "<cfoutput>\n\n<ul>\n <li>#includePartial(partial=customers, spacer=\"</li><li>\")#</li>\n</ul>\n\n</cfoutput>", "language": "text" } ] } [/block] [block:api-header] { "type": "basic", "title": "Partials and Grouping" } [/block] There is a feature of CFML that is very handy: the ability to output a query with the group attribute. Here's an example of how this can be done with a query that contains artists and albums (with the artist potentially being duplicated since they can have more than one album): [block:code] { "codes": [ { "code": "<cfoutput query=\"artistsAndAlbums\" group=\"artistid\">\n <!--- Artist info is displayed just once for each artist here --->\n <cfoutput>\n <!--- Each album is looped here --->\n </cfoutput>\n</cfoutput>", "language": "text" } ] } [/block] We have ported this great functionality into calling partials with queries as well. Here's how you can achieve it: [block:code] { "codes": [ { "code": "#includePartial(partial=artistsAndAlbums, group=\"artistId\")#", "language": "text" } ] } [/block] When inside the partial file, you'll have an additional subquery made available to you named `group`, which contains the albums for the current artist in the loop. [block:api-header] { "type": "basic", "title": "Using Partials with an Array of Objects" } [/block] As we've hinted previously in this chapter, it's also possible to pass in an array of objects to a partial. It works very similar to passing in a query in that the partial is called on each iteration. [block:api-header] { "type": "basic", "title": "Rendering or Including?" } [/block] So far we've only talked about [includePartial()](doc:includepartial), which is what you use from within your views to include other files. There is another similar function as well: [renderPartial()](doc:renderpartial). This one is used from your controller files when you want to render a partial instead of a full page. At first glance, this might not make much sense to do. There is one common usage of this though—AJAX requests. Let's say that you want to submit comments on your blog using AJAX. For example, the user will see all comments, enter their comment, submit it, and the comment will show up below the existing ones without a new page being loaded. In this case, it's useful to use a partial to display each comment (using [includePartial()](doc:includepartial) as outlined above) and use the same partial when rendering the result of the AJAX request. Here's what your controller action that receives the AJAX form submission would look like: [block:code] { "codes": [ { "code": "<cfset comment = model(\"comment\").create(params.newComment)>\n<cfset renderPartial(comment)>", "language": "text" } ] } [/block] Please note that there currently is no support for creating the AJAX form directly with Wheels. This can easily be implemented using a JavaScript library such as jQuery or Prototype though.