how adding global function in backbone.js accessible from multiple templates? - javascript

I have created two templates one for table and another for form inputs. The function which is in one template is not accessible from the other template . I want one global function which is accessible from both the template . I am new to backbone world . So is there any provision to do this ? Or is there any way access the function on one template from the another ?

There are a few ways of achieving this.
1. Add to Backbone directly
The simplest, but perhaps least desirable from a maintenance point of view, would be to add the function as a property of the Backbone object:
Backbone.myFunction = function (...) { ... };
2. Register a templating helper
The second option, depending on your templating engine of choice, you might be able to register helpers. Example:
Handlebars.registerHelper("myHelper", function (...) { ... });
3. Use dependency injection
A third option, if you are using something like require, would be to define the functions in a common dependency, and add it as a dependency to both views.

Related

How to create an instance of the Model Class in MVC Pattern - SapUI5

I am currently trying to implement the Model-View-Controller in my SAPUI5 / Fiori Project.
I managed to create an Instance of the Controller with: new sap.ui.core.mvc.Controller('controller.js')
This does not work for the Model (sap.ui.core.mvc does not contain a Model attribute).
Now I am searching a way to call functions of the Model from the Controller, to get my data.
I already tried this code: oObjModel = new sap.ui.mode.Model(), using this I cannot call functions from my Model.
I recommend you look at the walkthrough on the SAPUI5 documentation site. It shows how to initialize all the aspects of MVC in the correct way.
Models in SAPUI5 come in different classes to support different forms of data. For example, there is JSONModel, XMLModel, ODataModel, etc.
So to create a model, you need to first determine the specific type of model you need and use its specific constructor. For example, if you have JSON data (or simply a JavaScript object), you use the JSONModel:
var yourData = { "hello": "world" };
var oModel = new JSONModel(yourData);
Note that the above code assumes you are following the recommended way to use modules and that this code is wrapped with a sap.ui.define or sap.ui.require, where the module sap/ui/model/json/JSONModel is assigned to the variable JSONModel. The walkthrough shows this correct usage pattern. Accessing the constructor directly like the below is not recommended:
// Also probably works, but not the recommended way
var oModel = new sap.ui.model.json.JSONModel(yourData);
Your way of creating a controller is also not correct. You should preferably let the view instantiate the controller for you by providing it a controllerName, as shown in the walkthrough for Controllers.
<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" controllerName="name.of.your.controller">
<!-- ... -->
</mvc:View>
If you need to manually instantiate a controller from code, use this:
Controller.create({ name: "name.of.your.controller" }).then(function(oController) {
// Do something with oController
});
This again assumes you have the module sap/ui/core/mvc/Controller linked to the variable Controller.
Before version 1.56, you can use the now-deprecated sap.ui.controller function to create controllers instead:
sap.ui.controller("name.of.your.controller", null, /*async=*/true).then(function(oController) {
// Do something with oController
});
Be aware that both of these examples load the controller asynchonously, as synchronous XHR is being globally deprecated outside of Workers, and thus the framework recommends you to use async only. In fact, the new way of loading does not even provide an option for sync loading.

Inject a factory in a controller in angular

I´m trying to inject a factory in a controller in Angular, but I can not do. It is my code.
app.controller('ManejadorEventosVista', ['AdministradorMarcador', ManejadorEventosVista]);
'app' is the variable that corresponds to the module with their respective dependencies. The controller is 'ManejadorEventosVista' and requires the services provided by the factory 'AdministradorMarcador'.
function ManejadorEventosVista(){}
but when I want to use the factory 'AdministradorMarcador' in this part of the code , the factory is not recognized.
ManejadorEventosVista.prototype.seleccionarMarcadorOrigen = function (){
AdministradorMarcador.setTipoMarcador(AdministradorMarcador.MARCADOR_ORIGEN);
};
How I can do to use the factory
'AdministradorMarcador' in ManejadorEventosVista.prototype.seleccionarMarcadorOrigen??..
Help or example to guide me??..Thanks..
ManejadorEventosVista needs to take an argument and you will be able to reference the AdministradorMarcador inside the function as whatever you named the first variable. Like so
function ManejadorEventosVista(AdministradorMarcador){/**your code here**/}
What you are doing with the line fragment ['AdministradorMarcador', ManejadorEventosVista] is declaring that your function depends on AdministradorMarcador, but without providing an argument to ManejadorEventosVista, AngularJS doesn't know how you intend to reference AdministradorMarcador inside your controller.
This is done in order to allow AngularJS scripts to be minified, especially by already existing solutions, as they would change the variables your function takes to single letter names, making it impossible for AngularJS to determine which service or factory to inject. Annotation uses strings and position-based ordering to allow your script to work, even after being minified since strings won't be altered by the process.
See also Latest Stable docs on Annotation

How do I stop a naming clash in angularJS?

We have a service...
angular.module('app.services').service('Booking', function () {})
In our controller we do this...
angular.module('app.controllers')
.controller('PassengersController',
function (Booking) {
Booking.load();
...
Which has been fine up until now. However the application is growing and we need to create another 'Booking' object. This object should live under a different namespace to avoid naming clashes as I can't see how angular will inject the right dependency. For example we now need...
app.services --> Booking
app.states --> Booking
Ideally we would like to refactor our modules to represent the file structure which is now built by feature but trying one thing at a time does anyone know how I can tell angular to access this new booking object explicitly in my controllers?
I was thinking it could be like this....
angular.module('app.controllers')
.controller('PassengersController',
function (Booking) {
Booking.load();
var bookingState = app.states.Booking;
bookingState.goToNextState();
...
Thats ths pseudocode anyway, if it was just pure javascript easy peasy I would just make a global variable and attach some modules but I am not sure how we will do it so we can leverage angularJs's dependency injection and stop the naming clash!

Using controllerAs syntax in Angular, how can I watch a variable?

With standard controller syntax in AngularJS, you can watch a variable like:
$scope.$watch(somethingToWatch, function() { alert('It changed!'); });
Using the controllerAs syntax, I want to react to this change in an active controller. What's the easiest way to do this?
More detail, if it helps. I have one controller in a side pane that controls the context of the application (user selection, start time, end time, etc.). So, if the user changes to a different context, the main view should react and update. I'm storing the context values in a factory and each controller is injecting that factory.
You can always use a watcher evaluator function, especially helpful to watch something on the controller instance or any object. You can actually return any variable for that matter.
var vm = this;
//Where vm is the cached controller instance.
$scope.$watch(function(){
return vm.propToWatch;
}, function() {
//Do something
}, true);//<-- turn on this if needed for deep watch
And there are also ways to use bound function to bind the this context.
$scope.$watch(angular.bind(this, function(){
return this.propToWatch;
//For a variable just return the variable here
}), listenerFn);
or even ES5 function.bind:
$scope.$watch((function(){
return this.propToWatch;
}).bind(this), listenerFn);
If you are in typescript world it gets more shorter.
$scope.$watch(()=> this.propToWatch, listenerFn);
Eventhough you can watch on the controller alias inside the controller ($scope.watch('ctrlAs.someProp'), it opens up couple of problems:
It predicts (or in other words pre-determines) the alias used for the controller in the view/route/directive/modal or anywhere the controller is used. It destroys the purpose of using controllerAs:'anyVMAlias' which is an important factor in readability too. It is easy to make typo and mistakes and maintenance headache too since using the controller you would need to know what name is defined inside the implementation.
When you unit test the controller (just the controller), you need to again test with the exact same alias defined inside the controller (Which can probably arguably an extra step if you are writing TDD), ideally should not need to when you test a controller.
Using a watcher providing watcher function against string always reduced some steps the angular $parse (which watch uses to create expression) internally takes to convert the string expression to watch function. It can be seen in the switch-case of the $parse implementation

How to dynamically inject controller in AngularJS

How to set ng-controller as an expression from the $scope?
According to the documentation:
ngController – {expression} – Name of a globally accessible
constructor function or an expression that on the current scope
evaluates to a constructor function.
But how to evaluate scope expression as a controller for controllers that have been registered with module .controller?
For example:
Layout:
<div ng-controller="myExpr"></div>
JavaScript (define controller):
app.controller('myCtrl', ['$scope', '$timeout', function () { ... }];
JavaScript (parent scope):
$scope.myExpr = ...;
What should be in myExpr to use myCtrl as a controller via expression?
I've tried $controller('myCtrl')... not working...
P.S. If controller has been defined via globally accessible function.. it's possible to provide it as myExpr. But what to do if it has been defined so?
The expressions that ng-controller accept are a bit wierd. So you can do this by writing your controller slightly differently (but read below as for why you probably don't want to).
function myCtrl($scope) {
$scope.value = 'Stuff';
}
This is a controller and will work like normal for this case. Like in this example: http://jsbin.com/ubevel/2/edit
So why not do it?
First of all this is not a good way to define things from a testing perspective. Secondly, this allows you to set the controller dynamically on load but it won't allow you to change things after that. If you change the value of myExpr after the page has loaded the controller will not change.
So what to do?
I would highly suggest looking at using a service instead. Swap out your actions by supplying your outer controller with a service that you then change in the same manner you are now trying to change the inner controller. So something like: http://jsbin.com/ubevel/5/edit
This service can be swapped out on the fly, changing it will change the actions that are available in the scope.
You could also use an include, but this would result in duplicate html. I personalty am fine with this since I am against reusing html for two different types objects (sooner or later you want to change one but not the other and it becomes a mess). But a lot of people would object to that.
An extra note: There are probably nicer ways to do it with controllers, I probably haven't looked at all angles, but I just don't think controllers are the right tool for this case.

Categories

Resources