Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
In this section, you will find the release notes for each version we release under this major version. If you are looking for the release notes of previous major versions use the version switcher at the top left of this documentation book.
CBWIRE-24: File Uploads
CBWIRE-55: Ability to write unit tests for components
CBWIRE-59: Ability to override the default 'wires' folder location
CBWIRE-60: noRender() method to prevent template rendering during actions
CBWIRE-61: Implement dirty property tracking
CBWIRE-65: Invoke computed properties during template rendering and only execute once per request
CBWIRE-70: Ability to specify a 'moduleRootURI' setting to change the URI path for cbwire
CBWIRE-71: Upgrade Livewire JS to v2.10.6
CBWIRE-81: Option to specify the component's template path using this.template instead of defining renderIt() method.
CBWIRE-82: Disable browser caching on XHR responses
CBWIRE-83: Reduce payload bloat by removing unnecessary data in XHR requests and responses
CBWIRE-84: Move internal methods to a separate Engine object to avoid collisions with user-defined methods
CBWIRE-85: Reject incoming XHR request if 'X-Livewire' HTTP Header is not present
CBWIRE-86: Specify null values for data properties
CBWIRE-87: Dependency injection capabilities to cbwire components
CBWIRE-90: Update to match Livewire's current incoming and outgoing HTTP responses
CBWIRE-91: Ability to use Turbo to create Single-page Applications ( SPAs )
CBWIRE-73: Calling reset( "someProperty" ) throws error
CBWIRE-74: Browser back history doesn't work
CBWIRE-80: On subsequent renderings of components, it's changing the unique id and causing DOM diff issues
CBWIRE-88: Livewire expects params to be an array
CBWIRE-89: Not passing parameters when calling update methods
CBWIRE-111 Ability to output component template direct from onRender() method instead of defining a .cfm template in wire/views.
CBWIRE-119 Computed properties that do not return a value result in the error 'variable [VALUE] doesn't exist
CBWIRE-118 Nested components are causing the template rendering only to render the last nested template
CBWIRE-117 Struct values are not being passed to the template and are instead being replaced with an empty string
CBWIRE-116 CBWIRE doesn't work when the ColdBox app is in a subdirectory
CBWIRE-115 Getting errors when rendering component templates in the latest version of ColdBox
CBWIRE-96 Nested components are not rendering
With CommandBox, you can start building reactive CFML apps in seconds.
Adobe ColdFusion 2018+ or Lucee 5+
ColdBox 6+
Install CommandBox.
Within the root of your project, run:
If you want the latest bleeding edge, run:
You need to add references for wireStyles()
and wireScripts()
to your layout file.
CBWIRE will not work if you do not add these to your layout.
You can insert Wires anywhere in your layout or ColdBox views using wire( componentName )
.
Alter CBWIRE's behavior with these nifty configuration options.
You can alter any default behavior by overriding settings in your config/ColdBox.cfc
file.
Overriding the module settings is optional. All settings come with a default that is used if no overrides are provided. See Overriding Module Settings in the ColdBox documentation for additional reference.
Set as true to enable Turbo, which causes any clicked links or form submissions to be performed in the background via AJAX and updates the DOM without reloading the page. Great when developing single-page, VueJS-like applications. Defaults to false.
The maximum amount of time allowed for uploads to complete.
Set as true to throw a WireSetterNotFound exception if the incoming wire request tries to update a property without a setter on our Wire. Otherwise, missing setters are ignored. Defaults to false.
When set to true, any data properties that contain strings will be automatically trimmed. Great for form inputs. Defaults to false.
The relative folder path where Wires are stored. Defaults to 'wires'.
When set to true, Computed Properties will be proxied. See Computed Properties (Proxied).
CBWIRE is a ColdBox module that makes building modern, reactive CFML apps a breeze without the need for JavaScript frameworks such as Vue or React, and without the hassle of creating unnecessary APIs.
Are you tired of the challenges that come with building modern CFML apps? ColdBox makes server-side app development a breeze, but sometimes the client-side is a whole different story. With powerful JavaScript frameworks like Vue and React, it can be a difficult and time-consuming process to create your web apps.
But what if you could have the best of both worlds: the power of Vue and React with the simplicity of CFML? Impossible, you say? Think again!
Introducing CBWIRE: Power up your CFML and make your app dreams a reality!
Install CommandBox, then from our terminal, run:
Next, add wireStyles()
and wireScripts()
to our layout. This is required for CBWIRE to do it's magic.
Let's also insert a counter element into the page using wire( "Counter" )
.
Let's define our counter Wire.
Finally, let's create a Template for our counter Wire. Notice that we've added a wire:click
directive to our button.
Refresh the page. You now have a reactive counter that increments when you click the plus button without any page refreshing!
CBWIRE renders our Counter Wire template. Our counter value defaults to 0.
When a user clicks the plus button, CBWIRE detects the event and makes an XHR request to the server.
CBWIRE picks up the XHR request and invokes the increment action.
The increment method updates the counter state by 1.
CBWIRE re-renders the template and returns the updated HTML in the XHR response
CBWIRE detects any state changes and uses Livewire to mutate the DOM.
We built a reactive counter with no page refreshing.
We didn't write any JavaScript.
We didn't use webpack or mess with JavaScript compilation.
CBWIRE is transforming the way we build CFML applications, and we think you're going to love it also!
CBWIRE is built on Livewire and wouldn't exist without Caleb Porzio ( creator of Livewire, Alpine.js ) and the PHP community.
The CBWIRE module for ColdBox is written and maintained by Grant Copley, Luis Majano, and Ortus Solutions.
Please consider becoming one of our lovingly esteemed Patreon supporters.
CBWIRE Examples: https://github.com/grantcopley/cbwire-examples
ForgeBox: https://forgebox.io/view/cbwire
GitHub Repository: https://github.com/coldbox-modules/cbwire
Issue Tracker: https://github.com/coldbox-modules/cbwire/issues
Task List Demo: https://github.com/grantcopley/cbwire-task-list-demo
Form Validation Demo: https://github.com/grantcopley/cbwire-signup-form-demo
Up and Running Screencast: https://cfcasts.com/series/ortus-single-video-series/videos/up-and-running-with-cbwire
Into The Box 2021 Presentation: https://cfcasts.com/series/into-the-box-2021/videos/cbwire-coldbox-+-livewire-grant-copley
: Implement lifecycle hook onHydrate().
: Implement lifecycle hook onHydrate[Property]().
: Implement an automatic trim() for all data properties.
: Implement the ability to interact with CBWIRE component from JavaScript using cbwire.find( '#args._id#' ).
: Add configuration setting 'enableTurbo' to automatically include everything needed to work with Turbo for single page applications.
: Add ability to call reset() without passing a key to reset all data properties to their original values.
: Implement onMount() method instead of mount().
: DocBox generated docs are failing because of file structure.
: Listeners are being fired immediately when calling emit() when the listener is defined on the same component, which they shouldn't.
: onHydrate() is firing after actions are performed.
Create dynamic properties for your UI Wires.
If you are on CBWIRE version 2.3.x and have enabled the configuration property useComputedPropertiesProxy, then you will need to follow instead as this fundamentally changes how computed properties are referenced and accessed.
Computed Properties are dynamic properties and are helpful for deriving values from a database or another persistent store like a cache.
Computed Properties are similar to with some key differences:
They are declared as inline functions using computed
.
They can return any type of CFML value or object, not just values that can be serialized and parsed by JavaScript like Data Properties.
See the page for details on when Computed Properties are executed.
Computed Properties are cached for the lifetime of the request. Meaning, if you reference your Computed Property three times in your or from within a wire , it will only execute once.
You can define Computed Properties on your using computed
. Each Computed Property is invoked only once during a single request cycle.
Getters are automatically created based on the property's name.
In the example below, you to access the property using this.getAllTasks()
. You can use this as an alternative to using computed
.
Define reactive properties for your UI Wires with just a few lines of code.
Similar to Vue.js and other frontend JavaScript frameworks, you can define reactive properties on your .
You can define and initialize properties on your using data
.
Data Properties are parsed and tracked by Livewire and JavaScript, therefore only data types that are castable to JavaScript can be stored in Data Properties (strings, numeric, arrays, structs, or booleans). If you are needing more complex data types for your templates, use instead.
When data properties are mutated, the UI will update also.
You can reference a property using data.[propertyName]
.
Getter methods are automatically available for your properties based on the property's name. You to access the property within your Wire using this.get[propertyName]()
.
You can use this as an alternative to using data
.
You can reference data properties within your Wire's template using args.[propertyName]
.
You can reset properties back to their original value using reset()
.
There are several ways to use reset.
Your component's private variables
scope will hold your data property definitions and current values, but it's necessary to be cautious about what you store.
You should NEVER store sensitive data ( such as passwords, and SSNs ) that you wouldn't want your application's users to see.
Wires are reactive UI elements you create. They include a powerful feature-set provided by CBWIRE.
Wires primarily consist of the following:
Reactive properties that we can easily change.
Properties that are computed every time our template is rendered.
Methods that make state changes to our data properties.
Listen for emitted events within Wires or client-side JavaScript.
HTML to render our Wire.
From our CommandBox shell, type:
Let's create a Counter Wire that we will use to list our favorite movies.
You can provide named arguments as well.
We never left CFML.
: Computed properties are not being rendered before actions are called.
You can access your Computed Properties from within your using computed.[propertyName]
.
You can access Computed Properties in your via the args
scope.
The values of your data properties are included with each XHR response and Livewire uses these values to determine what should be updated in the .
You can scaffold Wires quickly using the module.
Create dynamic properties for your UI Wires.
You must be on CBWIRE version 2.3.5 or later and enable the Configuration setting useComputedPropertiesProxy to follow this guide.
Otherwise, please follow this guide instead.
In CBWIRE 2.3.5, we introduced the ability to proxy Computed Properties, which offers several advantages, including:
Computed Properties are passed around as closures and are only rendered when called.
The ability to invoke Computed Properties anywhere they are needed (both Actions and Templates).
The ability to cache Computed Property results to enhance performance.
Computed Properties are dynamic properties and help derive values from a database or another persistent store like a cache.
Computed Properties are similar to Data Properties with some key differences:
They are declared as inline functions using computed
.
They can return any CFML value or object.
Define Computed Properties in your Wires using computed
.
You can access your Computed Properties from within your Actions using computed.[propertyName]()
.
You can access Computed Properties in your Template using args.computed.[computedProperty]()
.
Everything that has a beginning has an end. - The Oracle, Matrix
When a Wire is initially loaded (before any background AJAX requests are performed), the Lifecycle Methods are executed in the following order.
onMount()
Render Computed Properties
onRender() or implicit Template rendering
For background AJAX requests, lifecycle methods are executed in this order.
onHydrate[DataProperty]()
onHydrate()
Render Computed Properties
Execute Actions
onRender() or implicit Template rendering
Runs only once when the Wire is initially wired.
This does not fire during subsequent renderings for the Wire.
onMount() replaces what was formerly mount(). The mount() method is deprecated and will be removed in future major releases of CBWIRE.
Runs on subsequent requests, after the Wire is hydrated, but before Computed Properties are rendered, before an Action is performed, or before onRender() is called.
Runs on subsequent requests, after a specific Data Property is hydrated, but before Computed Properties are rendered, before an Action is performed, or before onRender() is called.
Runs during the rendering of a Wire. If onRender() is defined on the Wire, CBWIRE will use what is returned as the component's template, otherwise it will perform a lookup for a view template. The args
parameter is provided which contains both the Data Properties and any rendered Computed Properties.
Your Wire's HTML. Simple as that. Honestly.
Wires require a template that contains the HTML to be rendered.
By default, Templates exist within your project under ./views/wires/[templateName].cfm
. You can override the default template location with the configuration setting templatesLocation.
See Configuration
If you haven't specified your template file name inside your Wire using template, a template will be implicitly loaded based on the Wire's file name.
For the example above, the template ./views/wires/tasklist.cfm
will be rendered.
File names should be lowercase when using Implicit Lookups. This is to avoid issues on case-sensitive file systems.
You can specify the path to your Template using template
.
In CBWIRE 1.x, you would define the template path using view
but this has been deprecated and template
should be used going forward.
Instead of creating a .cfm template, you can define an onRender() method on your Wire.
See the Wire Lifecycle page for additional details.
Within your Actions, you can call the method noRender()
to prevent your template from re-rendering. This can reduce the returned payload size for actions that do not change the UI.
Be sure your template includes a single outer element such as<div>
.
If an outer element is not detected, an OuterElementNotFoundexception is thrown.
You can use something other than <div></div>.
The magic sauce. Actions allow you to easily listen to page interactions and call a method on your Wires.
Actions provide an effortless way to track page interactions and invoke methods on your Wires, resulting in a re-render of the Wire's Template.
Here is a basic example of how to use it:
You can listen for browser events and invoke actions using a selection of various Directives. The directives follow the format: wire:[browser event]=[action].
Some examples of events you can listen for include:
Event | Directive |
---|---|
Here are a few examples of each in HTML:
You can listen for any browser events on elements by using the wire:[event] directive, where [event] is the event's name. For example, to listen for a "foo" event on a button element, you would use the following code:
You can pass parameters to your actions, such as here using addTask('Some Task')
.
The parameter is then passed through to your Actions via function arguments.
Actions shouldn't return any value. Return values are ignored.
You can access data properties inside your actions directly using data
.
You can access Computed Properties inside your actions directly using computed
.
Notice that our Computed Property above is defined as a closure function, but once our deleteTasks() action is called, the computed property has already been rendered.
In CBWIRE, there are some "magic" actions that are usually prefixed with a "$" symbol:
Consider the example below.
You can instead call $set and avoid the need to create an Action named setMessageToHello.
It can also be used in the backend when listening for an event. For example, if you have one component that emits an event like this:
Then in another component you can use a magic action for example $refresh() instead of having to point the listener to a method:
Seamlessly connect between the front-end and your server back-end using JavaScript and CFML.
CBWIRE gives you the opportunity to execute JavaScript during various events.
Hook | Description |
---|---|
You can interact with your Wires, calling Actions, setting Data Properties, and more, using cbwire.find from within your Wire Template. Once you have a reference to the Wire, you can interact with it using the methods below.
Toggle UI elements when the user is offline or online. Groovy!
You can use wire:offline
to display elements when Livewire detects that the user is offline.
You can also append .class
to your wire:offline
and specify a CSS class to toggle when the user is offline.
Use .remove
to specify classes you want to be removed when offline.
You can emit events from both your Wires and JavaScript. Superb!
You can emit events from , , and JavaScript.
Using the emit
method:
You can provide arguments to all listeners by passing an array as the second argument.
When emitting events, arguments must be passed as an array to ensure proper positioning both within CFML and JavaScript.
Using the $emit()
method:
Using the global cbwire.emit()
:
You can register event listeners on a Wire by defining listeners
.
The clearCache
method will be invoked when a taskAdded
event is emitted.
JavaScript keys are case-sensitive. You can preserve the key casing in CFML by surrounding your listener names in quotations.
CBWIRE makes uploading and storing files easy.
Here's an example of a simple Wire that handles uploading a photo:
Handling file inputs is no different than handling any other input type with CBWIRE. Add wire:model
to the <input>
tag and CBWIRE will take care of the rest.
There are several things happening under the hood to make file uploads work:
CBWIRE makes an initial request to the server to get a temporary "signed" upload URL.
Once the URL is received, JavaScript then does the actual "upload" to the signed URL, storing the upload in a temporary directory designated by CBWIRE and returning the new temporary file's unique hash ID.
Once the file is uploaded, and the unique hash ID is generated, CBWIRE makes a final request to the server, telling it to "set" the desired data property to the upload file as an instance of FileUpload ( see below ).
Now the data property (in this case photo
) is set to an instance of FileUpload@cbwire
and is ready to be stored or validated at any point.
CBWIRE will automatically upload your files and set your associated data property to an instance of FileUpload@cbwire
. Here are some of the methods you can use that can get quite helpful.
You can display a loading indicator scoped to the file input during upload like so:
The "Uploading..." message will be shown as the file is uploading and then hidden when the upload is finished.
Front-end testing of your UI Wires using a beautiful test API.
Similar to ColdBox, you can relocate users using relocate.
You can redirect users in your using relocate()
.
Redirects a user to a different URI, URL, or event.
CBWIRE's relocate() method signature is nearly identical to ColdBox's internal relocate() method, with the exception that status codes cannot be set. Otherwise, most of the arguments that ColdBox accepts can be used.
include powerful validations that you can use to validate your .
Validations are provided by .
You can define constraints within your wires using this.constraints
.
can validate against the defined constraints using validate()
or validateOrFail()
.
Returns a ValidateResult
object.
With validateOrFail(),
the error is gracefully caught and any further processing of the invoked action is prevented. The XHR response and re-rendered template are still returned. The actual errors themselves are available to the template using args.validation
.
If you need more granular control over the validation response, use validate()
instead.
You can get a new ValidationManager object to work with, just call getValidationManager()
;
It can be useful at times to update the browser's query string when your state changes.
Let's say you are building a to search articles, and want the query string to reflect the current search value like so:
This way, when a user hits the back button or bookmarks the page, you can get the initial state out of the query string rather than resetting the every time.
You can add a queryString
variable to your and CBWIRE will update the query string every time the property value changes and also update the property when the query string changes.
Function | Description |
---|---|
Listening to events that you emit in your can be done using cbwire.on()
.
Method | Description |
---|
This works with the entire .
Set a to the specified value.
Set a to the specified closure.
Toggles a between true and false.
Calls an . Optional array of parameters can be provided.
Emits an and fires any that are defined on the . Optional array of parameters can be provided, which will be passed on to listeners.
Verifies a value can be found in the current rendering. Otherwise, test fails.
Verifies a value is not found in the current rendering. Otherwise, test fails.
Verifies a matches a specified value. Otherwise, test fails.
Verifies a does not match a specified value. Otherwise, test fails.
Silently fails and prevents further processing of the current .
can access the ValidationResults object using args.validation
. This includes helpful methods you can use for displaying error messages.
click
wire:click
keydown
wire:keydown
submit
wire:submit
$refresh
Will re-render the component without firing any action
$set( 'dataproperty', value )
Shortcut to update the value of a property
$toggle( 'dataproperty' )
Shortcut to toggle boolean properties off and on
component.initialized
Called when a Wire has been initialized on the page by Livewire
element.initialized
Called when Livewire initializes an individual element
element.updating
Called before Livewire updates an element during its DOM-diffing cycle after a network roundtrip
element.updated
Called after Livewire updates an element during its DOM-diffing cycle after a network roundtrip
element.removed
Called after Livewire removes an element during its DOM-diffing cycle
message.sent
Called when a Livewire update triggers a message sent to the server via AJAX
message.failed
Called if the message send fails for some reason
message.received
Called when a message has finished its roudtrip, but before Livewire updates the DOM
message.processed
Called after Livewire processes all side effects (including DOM-diffing) from a message
getComp() | Returns an instance of your current Wire. |
getParams() | Returns any params that are passed in, including the data property name. |
get() | Returns the contents of the file uploaded. |
getBase64() | Returns base64 encoded string of the file. |
getBase64Src() | Returns a base64 src string that can be used with <img tag>. It is recommended to use this carefully because with larger objects, this can slow down CBWIRE response times. |
getTemporaryStoragePath() | Returns the temporary storage path where the file is stored by CBWIRE. |
getMetaPath() | Returns the file path to meta information of the uploaded file. You can find additional details here like the name of the file when it was uploaded, the client file extension, etc. |
getMeta() | Returns all captured meta information on the file upload. |
getSize() | Returns the size of the file upload. |
getMimeType() | Returns the mime type of the file upload. |
isImage() | Returns true if this is an image. |
getPreviewURL() | Provides a URL to preview the file uploaded. It only works with image uploads. |
destroy() | Deletes the temporary storage and metadata of the file upload. It's essential to use this after storing the file upload in permanent storage. |
Poll for state changes based on a specified interval without page refreshes. Hot dog!
You can add a wire:poll
directive to your elements to poll for changes using a set interval. The default interval is set to poll every 2 seconds.
You can append a different interval time to your directive as well.
Polling for changes over AJAX can be a resonable alternative to strategies such as Pusher or WebSockets.
If you would like to invoke a method during each poll interval, you can do so by specifying a method name.
If you want stop polling, you can simply no longer render the HTML element that has the wire:poll
directive.
Prefetch state changes when the user mouses over an HTML element. Fantastico!
You can prefetch an Action's results on mouseOver using the .prefetch
modifier.
In the example here, the togglePreview
action will be prefetched and invoked when the user mouses over the button. The results of the fetch are not displayed until the user clicks the 'Show Preview' button.
Prefetching works well for actions that do not perform any side effects, such as mutating session data or writing to a database. If the action you are "pre-fetching" does have side effects, you may encounter unpredictable results.
Just as with ColdBox, you can inject your dependencies using WireBox.
CBWIRE's powerful directives allow you to listen for client side events, invoke actions, bind to data properties, and more.
The following Directives can be added to your Templates and instruct CBWIRE how and when to update the Wire.
Define a key name foo
for the element. This provides a reference point for the Livewire DOM diffing system. Useful for adding/removing elements and keeping track of lists.
Listens for a click
event and invokes the foo
Action.
You will want to add the .prevent modifier to ensure that the browser doesn't follow the link.
Listens for a mouseEnter
event and then prefetches the result of the foo
Action. If the element is then clicked, it will swap in the prefetched result without any extra request. If it's not clicked, the cached results will be thrown away.
Listeners for a submit
event on a form.
You will want to add the .prevent modifier to ensure that the browser doesn't submit the form.
Listens for a keyDown
event and invokes the foo
Action.
Listens for a keyDown
event when the user hits enter and invokes the foo
Action.
Listens for a foo
event and invokes the bar
Action.
You can listen to any JS event, not just those defined by Livewire.
Provided you have data[ "foo" ]
defined in your Data Properties, this creates a one-to-one model binding. Any time the element is updated, the value is synchronized.
The same as wire:model="foo"
except that all input events to the element will be debounced for the specified duration. Defaults to 150 milliseconds. Useful for reducing XHR background requests during user input. You can set the milliseconds value to any numeric value.
Creates a one-to-one model binding with data[ "foo" ]
in your Data Properties but defers any XHR updates until an Action is performed. Useful for reducing XHR requests.
Creates a one-to-one model binding with data[ "foo" ]
in your Data Properties but will not perform an XHR updates until an onBlur
event is emitted. Useful for reducing XHR requests.
If your input field does not require immediate updating ( such as for instant form validation), we highly recommended you used the lazy modifier to reduce the number of XHR requests .
Performs an XHR request to re-render the elements based on a set interval. An interval can be specified in both seconds or milliseconds. You can also specify an Action that you want to invoke. See Polling
Invokes the foo
Action on your Wire immediately after it's rendered on the page.
Hides the HTML element by default and makes it visible when XHR requests are performed.
Adds the foo
class to the HTML element while XHR requests are in transit.
Removes the foo
class from the HTML element while XHR requests are in transit.
Adds the disabled="true"
attribute while XHR requests are in transit.
Hides the HTML element by default and makes it visible when the element's state has changed since the latest XHR request.
Adds the foo
class to the HTML element when the element's state has changed since the latest XHR request.
Removes the foo
class from the HTML element when the element's state has changed since the latest XHR request.
Adds the disabled="true"
attribute when the element's state has changed since the latest XHR request. Used in addition to wire:target
.
Provides scoping for wire:loading
and wire:dirty
references, scoped to a specific Action.
Instructs Livewire to not update the element or any child elements when updating the DOM. Useful when using third-party JavaScript libraries.
Instructs Livewire to not update the element but DOES allow updates to any child elements when updating the DOM.
See Offline State
CBWIRE Directives sometimes offer "modifiers" to add extra functionality to an event. Here are the available modifiers that can be used with any event.
To listen for specific keys on keydown events, you can provide the name of the key as a modifier. You can use any valid key names exposed via KeyboardEvent.key as modifiers by converting them to kebab-case.
Here is a quick list of some common ones you may need:
In the above example, the foo Action will only be called if event.key
is equal to 'PageDown'.
Help website users during wait times using Loading States.
Actions may involve a long-running process (such as completing a cart checkout) and HTML may not re-render instantly. You can help your users during the wait using Loading States. Loading States allow you to show/hide elements, add/remove classes, or toggle HTML attributes until the server responds.
Loading States can make your apps feel much more responsive and user-friendly.
Let's look at an action that takes too long.
We can annotate our <div>
with wire:loading
to display Adding Task while the checkout action is running.
You can target a specific action so that the element is only visible is a specific action is loading using wire:target
.
If you want to avoid flickering because loading is very fast, you can add a .delay
modifier, and it will only show up if loading takes longer than 200ms
.
If you wish, you can customize the delay duration with the following modifiers:
Loading State elements are set with a CSS property of display: inline-block;
by default. You can override this behavior by using various directive modifiers.
If you would like to display an element except during a loading state, you can apply the wire:loading.remove
directive.
Track changes to Data Properties and display changes in your UI instantly.
There are cases where it may be helpful to provide feedback that content has changed and is not yet in sync with the back-end. For input that uses wire:model
, or wire:model.lazy,
you can display that a field is 'dirty' until CBWIRE has fully updated.
Adding the .class
modifier allows you to add a class to the element when dirty.
You can perform the inverse and remove classes by adding the .remove
modifier.
The default behavior of the wire:dirty
directive without modifiers is that the element is hidden until dirty. This can create a paradox if used on the input itself, but like loading states, the dirty
directive can be used to toggle the appearance of other elements using wire:target.
In this example, the span
is hidden by default and only visible when the input element is dirty.
Use the class and attribute modifiers in the same way for referenced elements.
Beautifully integrate your client-side JavaScript and CBWIRE using AlpineJS.
Many page interactions don't warrant a full server roundtrip, such as toggling a modal or a hidden element. In these instances, we recommend using .
AlpineJS allows you to add JavaScript behavior directly into your markup in a declarative way. If you are familiar with VueJS, Alpine should feel similar.
For more installation information, visit the .
Below is an example of using to toggle a list on the page.
You need CBWIRE v2.3.6 or greater to use entangle.
CBWIRE has a powerful entangle() method that allows you to "entangle" a CBWIRE and AlpineJS data property. With entanglement, both client-side and server-side properties are instantly synchronized, regardless of whether the value was changed server-side in CFML or client-side using JavaScript.
This provides data model binding both client-side and server-side.
And now, our template:
We define an AlpineJS property named counter and then call the built-in CBWIRE method entangle(), passing it the name of the server-side data property we want to bind with.
Next, we are incrementing our Counter in two separate ways:
Updating CBWIRE server-side on every AlpineJS property change is optional. You can also delay the server-side updates until the next CBWIRE request that goes out by chaining a .defer modifier like so.
You can listen for livewire:load and place any JavaScript there.
We recommend you use for most of your JavaScript needs, but you can use <script>
tags directly inside your .
Your scripts will be run only once upon the first render of the component. If you need to run a JavaScript function later, you can emit the from the component and listen to it in JavaScript.
Remove full-page reloads from your applications and create single-page applications with ease using Turbo.
Turbo is an open-source library that accelerates links and form submissions by negating the need for full page reloads. With Turbo, you get all the following included:
Links and form submissions are performed in the background using AJAX instead of performing full page reloads
Browse history management, so clicking the back and forward buttons in the browser work as expected
Internal caching that improves perceived performance by showing temporary previews during network requests and while the page is updated
And much more!
CBWIRE and Turbo together allow you to quickly build single-page applications in record time.
For additional information on how Turbo can be used and configured, please see
You can enable Turbo with the enableTurbo , which automatically wires up everything needed to start using Turbo. Once enabled, links and form submissions will automatically be performed in the background via AJAX instead of performing full page reloads.
You can alternatively perform a of Turbo instead.
Use the manual installation when you want more control over where Turbo is included within your HTML.
You can install Turbo by running the following npm
command in the root of your project.
Then you can require or import Turbo.
For Turbo to work properly with Livewire (and therefore CBWIRE), you will also need to include the Turbo plugin below your wireScripts()
call in your layout.
Note: You MUST have either the data-turbolinks-eval="false"
or data-turbo-eval="false"
attributes added to the script tag (having both won't hurt).
During Turbo navigation, the browser will not display its native progress indicator. Turbo installs a CSS-based progress bar to provide feedback while issuing a request.
The progress bar is enabled by default. It appears automatically for any page that takes longer than 500ms to load.
The progress bar is a <div>
element with the class name turbo-progress-bar
. Its default styles appear first in the document and can be overridden by rules that come later.
For example, the following CSS will result in a thick green progress bar:
In your layout file, you can include the progress bar like so:
Preload links into Turbo Drive’s cache using data-turbo-preload.
This will make page transitions feel lightning fast by providing a preview of a page even before the first visit. Use it to preload the most important pages in your application.
Avoid over usage, as it will lead to loading content that is not needed.
Call an action immediately once your Wire is first rendered.
You can use the wire:init
to execute an action as soon as your component is initially rendered.
This can be helpful in cases where you don't want to hold up the entire page load, but want to load some data immediately after the page load.
Modifier | |
---|---|
Native Browser Event | Livewire Modifier |
---|---|
After the action completes, the Adding Task... output will disappear.
Consider this simple Counter :
Incrementing the counter by calling the increment using CBWIRE
Incrementing the AlpineJS property counter value in JavaScript, triggering an immediate update to the server and re-rendering of the Counter .
To avoid manual installation, there is also a available which you can add to the <head></head> of your layout.
stop
Equivalent of event.stopPropagation()
prevent
Equivalent of event.preventDefault()
self
Only triggers an action if the event was triggered on itself. This prevents outer elements from catching events that were triggered from a child element. (Like often in the case of registering a listener on a modal backdrop)
debounce.300ms
Adds an Xms debounce to the handling of the action.
Backspace
backspace
Escape
escape
Shift
shift
Tab
tab
ArrowRight
arrow-right
You can use CBWIRE alongside ContentBox to build modernize, reactive applications with a powerful CMS included.
ContentBox is a professional open source hybrid modular CMS (Content Management System) that allows you to easily build websites, blogs, wikis, complex web applications and even power mobile or cloud applications. Built with a secure and flexible modular core, designed to scale, and combined with world-class support, ContentBox will get your projects out the door in no time.
You need to install CBWIRE version 2.3.3 or later in order to be able to use CBWIRE and ContentBox.
In the root of your ContentBox application, install CBWIRE using CommandBox. The example below installs the latest bleeding-edge version.
Once installed, you will need to restart your app using ?fwreinit=[your secret key].
Ensure that CBWIRE is installed under /modules/cbwire from the root of your project. It should be installed there by default. Installing CBWIRE elsewhere can cause errors within a ContentBox application.
You will need to use a custom theme in order to integrate with CBWIRE.
If you are wanting to use a theme that is included with ContentBox or one that you've pulled down from ForgeBox, you can copy the theme code over to the folder modules_app/contentbox-custom/_themes.
Once CBWIRE is installed, you should have access to the three core included methods and should be able to reference these within your layout and theme templates.
wireStyles() - Pulls in required styling for CBWIRE
wireScripts() - Pulls in required JavaScript assets for CBWIRE/Livewire
wires() - Includes a Wire (reactive UI element) you create
In your theme layout, you need to place wireStyles()
within your <head> tags, wireScripts()
before the end of </body>, and you can call wire()
to include your reactive UI Wires where needed.
You can also reference the wire() method within your views.