AngularJS self-learning path (3)-controller and expression, and angularjs self-study
Controller
The role of the Controller in AngularJS is to enhance the view.
The Controller in AngularJS is a function used to add additional functions to the view scope. We use it to set the initial state for the scope object and add custom behavior.
When we create a new controller on the page, AngularJS will generate and pass a new $ scope to this controller. You can initialize the scope in this controller. AngularJS is responsible for processing the instantiation process of the controller, so we only need to compile the constructor. The following example shows controller initialization:
Careful readers will find that we create this function in the global scope. This is not suitable because it will pollute the global namespace. A more reasonable way is to create a module and then create a controller in the module, as shown below:
You only need to create functions in the Controller scope to create custom operations that can be used in the view. Fortunately, AngularJS allows us to call functions on $ scope in a view just like calling common data.
With the built-in command ng-click, you can bind buttons, links, and other DOM elements to the click event. The ng-click Command binds the browser's mouseup event together with the event handler set on the DOM element (for example, when the browser triggers a click event on a DOM element, ). Similar to the preceding example, binding looks like this:
The buttons and links are bound to an internal $ scope operation. When you click any element, AngularJS will call the corresponding method. Note: When you set which function to call, a parameter (add (1) will be passed in parentheses at the same time )).
Next, add an operation to FirstController:
app.controller('FirstController', function($scope) {$scope.counter = 0;$scope.add = function(amount) { $scope.counter += amount; };$scope.subtract = function(amount) { $scope.counter -= amount; };});
The controller can encapsulate the business logic related to an independent view in an independent container. It is a good practice to streamline the Controller as much as possible. As AngularJS developers, using dependency injection to access services can achieve this goal.
An important difference between AngularJS and other JavaScript frameworks is that controllers are not suitable for DOM operations, formatting, or data operations, as well as State maintenance operations other than data model storage. It is only a bridge between the view and $ scope.
Controller nesting (scope includes scope) By default, AngularJS searches for an attribute in the parent scope when it cannot be found in the current scope. If AngularJS cannot find the corresponding attribute, it will keep searching up along the parent scope until it reaches $ rootScope. If rootScope cannot be found, the program continues to run, but the view cannot be updated.
Let's look at this behavior through an example. Create a ParentController that contains a user object and create a ChildController to reference this object:
app.controller('ParentController', function($scope) {$scope.person = {greeted: false};});app.controller('ChildController', function($scope) {$scope.sayHello = function() {$scope.person.name = 'Ari Lerner';};});
If we place ChildController inside ParentController, the $ scope object parent scope of ChildController is the scope object of ParentController. Based on the prototype Inheritance Mechanism, we can access the scope object of ParentController in the subscope.
For example, we can access the person object defined in ParentController In the DOM element of ChildController.
<div ng-controller="ParentController"><div ng-controller="ChildController"><a ng-click="sayHello()">Say hello</a></div>{{ person }}</div>
We can see that when you click the button, you can access the $ scope. person value in ParentController in ChildController, as if the person object is defined in the scope of ChildController.
The Controller should be as short as possible, while DOM operations and data operations in the controller are not a good practice.
Well-designed applications place complex logic in commands and services. By using commands and services, we can reconstruct the controller into a lightweight and easy-to-maintain form.
Simple controller:
Angular. module ('myapp', []). controller ('mycontroller', function ($ scope, UserSrv) {// The content can be controlled by commands $ scope. onLogin = function (user) {UserSrv. runLogin (user );};});
Expression We have seen examples using expressions before. Binding a variable to $ scope using the {} symbol is essentially an expression: {expression }}. When you use watch for listening, AngularJS performs operations on expressions or functions.
Expressions are very similar to eval (javascript), but since expressions are processed by AngularJS, they have the following notable differences:
Any operation on an expression is executed within the scope of the expression. Therefore, you can call variables that are restricted within this scope within the expression, and loop, function call, apply the variable to the mathematical expression medium operation.
Parse AngularJS expressions Although AngularJS automatically parses the expression while running the $ digest loop, it is useful to manually parse the expression.
AngularJS uses the $ parse Internal Service to perform expression operations. This service can access the current scope.
Inject the $ parse service into the controller and call it to implement a manual parsing expression. For example, if an input box on the page is bound to the expr variable, as shown below:
<div ng-controller="MyController"><input ng-model="expr" type="text" placeholder="Enter an expression" />
In MyController, we can set a $ watch expression for expr and parse it:
Angular. module ("myApp", []). controller ('mycontroller', function ($ scope, $ parse) {$ scope. $ watch ('expr', function (newVal, oldVal, scope) {if (newVal! = OldVal) {// use this expression to set parseFunvar parseFun = $ parse (newVal); // obtain the value of the parsed expression $ scope. parsedValue = parseFun (scope );}});});
Interpolation string In AngularJS, we do have the ability to manually run template compilation. For example, interpolation allows text strings to be updated in real time based on a condition in the scope.
To perform interpolation in the string template, You need to inject $ interpolate service into your object. In the following example, we will inject it into a controller:
Angular. module ('myapp', []). controller ('mycontroller', function ($ scope, $ interpolate) {// We have permissions to access $ scope and $ interpolate services at the same time });
$ Interpolate is a function that accepts three parameters. The first parameter is required.
$ Interpolate returns a function used to calculate expressions in a specific context.
After these parameters are set, you can perform character interpolation in the controller. For example, if we want to edit the text in real time in the body of the email, perform the character interpolation operation when the text changes and display the result.
<div ng-controller="MyController"><input ng-model="to"type="email"placeholder="Recipient" /><textarea ng-model="emailBody"></textarea><pre>{{ previewText }}</pre></div>
Because the controller has a custom input field that requires re-interpolation of characters for each change, you need to set a $ watch to listen for data changes.
In short, the $ watch function monitors an attribute on the scope. The corresponding function is called as long as the attribute changes. You can use the watch function to directly run a custom function when a property on the scope changes.
In the controller, we set $ watch to monitor the changes in the mail body, and assign the value of the emailBody attribute to the previewText attribute after the result of character interpolation.
Angular. module ('myapp', []). controller ('mycontroller', function ($ scope, $ interpolate) {// set the listener $ scope. $ watch ('emailbody', function (body) {if (body) {var template = $ interpolate (body); $ scope. previewText = template ({to: $ scope. to}) ;}};}); In
Now, you can use {to} as a variable in the {previewText} text and update the text changes in real time.
You can use the startSymbol () method to modify the start symbol. This method accepts a parameter.
You can use the endSymbol () method to modify the end symbol. This method also accepts a parameter.
To modify the settings of these two symbols, You need to inject $ interpolateProvider into the new module.
Angular. module ('emailparser ', []). config (['$ interpolateProvider', function ($ interpolateProvider) {$ interpolateProvider. startSymbol ('_'); $ interpolateProvider. endSymbol ('_') ;}]). factory ('emailparser ', [' $ interpolate ', function ($ interpolate) {// process the parsed service return {parse: function (text, context) {var template = $ interpolate (text); return template (context) ;};}]);
Now we have created a module that can inject it into the application and run the email parser in the text of the mail body:
Angular. module ('myapp', ['emailparser ']). controller ('mycontroller', ['$ scope', 'emailparser ', function ($ scope, EmailParser) {// set the listener $ scope. $ watch ('emailbody', function (body) {if (body) {$ scope. previewText = EmailParser. parse (body, {to: $ scope. to}) ;}}) ;}]);
Now, use the custom _ symbol to replace the {} symbol in the default syntax to request the interpolation text.
Because we set the start and end symbols of the expression to __, we need to modify the HTML to replace the version of {} with this symbol,
<div id="emailEditor"><input ng-model="to"type="email"placeholder="Recipient" /><textarea ng-model="emailBody"></textarea></div><div id="emailPreview"><pre>__ previewText __</pre></div>