Scoped Variables are the method that Erstwhile uses to pass variables and functions between the controller and view layers.
At the present time, Erstwhile has three different scopes available:
- session: session scoped variables are tied to the browser session
- page: page scoped variables are tied to the current page
- modal: modal scoped variables are tied to the modal
When dealing with data, the developer should generally choose a scope that most closely matches when the data needs to be available. If the data lives as long as the user is logged in to your site like a username, it makes sense to use the session scope. Items that will need to be refreshed each time a user revisits a page should be at the page scope. Makes sense, right?
Controller Level
Within the controller, developers can assign and update Scoped Variables like this:
// assigning a single variable
$App.scopes.page.title = "Login";
// assigning an function (to serve as an event handler)
$App.scopes.page.submitForm = function() {
$App.getComponent("login-alert").hide();
let formValues = $App.getComponent("login-form").getValues();
let model = $App.getModel('Authentication');
model.login(formValues).then(function(response) {
if(response.data.success) {
model.currentUser().then(function(response) {
$App.scopes.session.user = response.data;
let queryParams = new URLSearchParams(location.search);;
if(queryParams.get('redirect')) {
$App.redirect(queryParams.get('redirect'))
} else {
$App.redirect("/todos/list")
}
}).catch(function(e) {
console.log(e)
});
} else {
$App.getComponent("login-alert").show();
}
}).catch(function(e) {
console.log("error", e)
});
return false;
}
}Under $App.scopes there are the three available scopes: session, page, and modal.
View Level
Within the views (and layouts) you can pass your Scoped Variables/Functions to your ErstwhileComponents like this:
<!-- assigning a regular variable -->
<Form id="edit-todo">
<TextInput name="title" label="Title" required="true" value="@.page.todo.title" />
<DateInput name="date" label="Date" value="@.page.todo.date" />
<SelectInput name="color" label="Color" value="@.page.todo.color">
<option value="green">Green</option>
<option value="blue">Blue</option>
<option value="orange">Orange</option>
<option value="red">Red</option>
<option value="yellow">Yellow</option>
</SelectInput>
<TextareaInput name="description" label="Description" helpText="This should be a description if the todo if necessary." rows="10" required="true" value="@.page.todo.description" />
<SwitchInput name="done_flag" label="Completed" value="@.page.todo.done_flag" />
<TextareaInput name="completion_notes" label="Completion Notes" helpText="Anything else to add about this todo?" rows="10" required="false" value="@.page.todo.completion_notes" />
</Form>
<!-- assigning an event handler -->
<Button color="primary" onclick="@.page.submitForm">Login</Button>The syntax @.page (or @.session or @.modal) indicates that the variable is meant to be accessed as a Scoped Variable and not as just a standard string.
What’s Happening Under the Hood
When a Scoped Variable is assigned to a component in the view, it creates a watch for that component. Any subsequent updates to that variable within the controller (or within an event handler) will be transmitted to the component via the component’s receiveUpdate() method; this gives the component the ability to decide on what it wants to do with that update.
Event handlers (that is, attributes that start with on*) are handled slightly differently. If they are assigned a Scoped Function, that function will be added as the named handler for that component.
Once the scope expires (for example, when a new page is loaded in the case of page scope), the watches are removed for that scope.