Angular 2+ services to angularJs - angularjs

I m trying to convert Angular 2+ service and use it in angularJs project.
app/users.service.ts
import { Injectable } from '#angular/core';
#Injectable()
export class UsersService {
private users: any = [
{ id: 1, name: 'john' },
{ id: 2, name: 'jane' }
];
constructor() { }
getUsers() {
return this.users;
}
}
then I tranform it into js with rollup
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('#angular/core'), require('#angular/upgrade/static'), require('#angular/platform-browser')) :
typeof define === 'function' && define.amd ? define(['exports', '#angular/core', '#angular/upgrade/static', '#angular/platform-browser'], factory) :
(factory((global.mymodule = {}),global.ng.core,global._static,global.platformBrowser));
}(this, (function (exports,core,_static,platformBrowser) { 'use strict';
var UsersService = /** #class */ (function () {
function UsersService() {
this.users = [
{ id: 1, name: 'john' },
{ id: 2, name: 'jane' }
];
}
UsersService.prototype.getUsers = function () {
return this.users;
};
UsersService.decorators = [
{ type: core.Injectable },
];
/** #nocollapse */
UsersService.ctorParameters = function () { return []; };
return UsersService;
}());
var MyModule = /** #class */ (function () {
function MyModule(upgrade) {
this.upgrade = upgrade;
}
MyModule.decorators = [
{ type: core.NgModule, args: [{
imports: [platformBrowser.BrowserModule, _static.UpgradeModule],
declarations: [],
providers: [UsersService],
exports: []
},] },
];
/** #nocollapse */
MyModule.ctorParameters = function () { return [
{ type: _static.UpgradeModule, },
]; };
return MyModule;
}());
exports.UsersService = UsersService;
exports.MyModule = MyModule;
Object.defineProperty(exports, '__esModule', { value: true });
})));
I add downgradeInjectable to convert angular2+ service into angularJs
angular.module('users.service', [])
.factory('usersServices', downgradeInjectable(usersServices));
next I try to load it in angularJs
(function() {
'use strict';
angular.module(
'ng1.module', [
'usersServices'
]);
})();
I m missing something because it doesn't work :/
I can't find ressource to do it, all people a trying to convert ng1 service to ng2 but not the reverse.
Someone can help ?
Thank you

Instead of importing 'usersServices' (the service factory) in the module 'ng1.module', you should import the actual module with 'usersServices' in it instead:
(function() {
'use strict';
angular.module(
'ng1.module', [
'users.service'
]);
})();

Related

Angular JS 1.X Component Inheritance

How does one achieve inheritance with Angular JS components? My sample is:
app.component('ResourceForm', controller: [
function () {
this.save = () => {
$http(this.path, this.attributes());
};
},
]);
app.component('PersonForm', {
bindings: {
person: '<person',
},
controller: [
function () {
this.path = '/person/' + this.person.id;
this.attributes = () => { name: this.name };
},
],
});
<!-- templates/person_form.html -->
<form>
<input type="text" ng-model="$ctrl.name" >
<submit ng-click="$ctrl.save()"></submit>
</form>
As far as I know there is no real inheritance. You can play with configs to get some kind of inheritance:
var cfg = {
bindings: {
person: '<person',
age: '#',
onNameChange: '#'
}
}
var component1 = angular.copy(cfg);
component1.controller = ctrl1;
app.component('component1', component1);
var component2 = angular.copy(cfg);
component2.controller = ctrl1;
app.component('component2', component2);

Example of injecting services in Angular 1.5 components

Can anyone give an example on using services with Angular 1.5 components?
I'm trying to inject a service in an Angular 1.5 component, but it doesn't work.
I have a login component like so:
class Login {
constructor($scope, $reactive, $state, myService) {
console.log(myService.somevariable); //doesn't work
}
}
// create a module
export default angular.module(name, [
angularMeteor
]).component(name, {
templateUrl: 'imports/ui/components/${name}/${name}.html',
controllerAs: name,
controller: Login
});
My service looks like this:
angular.module(name).service("myService", function () {
this.somevariable = 'somevalue';
});
I just cant seem to be able to get the service injected in the component.What am I doing wrong?
SOLUTION:
With sebenalern's help, I got it working.
I needed a service to validate an email address using a regular expression. I did it like this:
import angular from 'angular';
import angularMeteor from 'angular-meteor';
class Validator {
validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
}
const name = 'validator';
// create a module
export default angular.module(name, [
angularMeteor
])
.service("Validator", Validator);
I then injected the service like so:
import {name as Validator} from '../../../api/services/validator'
class Login {
constructor($scope, $reactive, $state, Validator) {
'ngInject';
this.$state = $state;
$reactive(this).attach($scope);
this.Validator = Validator;
}
login() {
if(this.Validator.validateEmail(this.credentials.email)) {
// email is valid.
}
}
}
const name = 'login';
export default angular.module(name, [
angularMeteor,
Validator
]).component(name, {
templateUrl: `imports/ui/components/${name}/${name}.html`,
controllerAs: name,
controller:Login
})
Hope this helps :)
So one problem I see is you should be using the keyword this inside the constructor
this.$scope = $scope;
Another thing it is probably easier to stay away from classes and use functions:
class Login {
constructor($scope, $reactive, $state, myService) {
console.log(myService.somevariable); //doesn't work
}
}
Becomes:
angular
.module('name')
.service('myService', myService);
function myService () {
this.somevariable = 'somevalue';
}
To me it seems a lot cleaner. Also another thing about ES6 classes is
ES6 Classes are not hoisted, which will break your code if you rely on hoisting
For more info see link.
Now here is the working code I came up with:
First we declare the module:
angular.module('name', []);
Next we register our service and then create the service definition:
angular
.module('name')
.service('myService', myService);
function myService () {
this.somevariable = 'somevalue';
}
Next we do the same procedure for our controller and also we inject $scope and our service into it.
angular
.module('name')
.controller('Login', Login);
function Login($scope, myService) {
$scope.someVar = myService.somevariable;
}
Last I registered our component:
angular
.module('name')
.component('my-html', {
templateUrl: 'my-html.html',
controller: Login
});
And that is it on the javascript side.
Here is my html code:
<!DOCTYPE html>
<html lang="en-us" ng-app='name'>
<head>
<script src="//code.angularjs.org/1.5.0-rc.1/angular.js"></script>
<script src="controller.js"></script>
</head>
<body >
<h ng-controller="Login">{{ someVar }}</h>
</body>
</html>
I hope this helps!!
Here is how I am doing it and it works well. It works fine with classes. I assume you are using TypeScript.
class AdminHomeService {
consignment: IConsignment;
get: () => IConsignment;
constructor() {
this.consignment = new Consignment();
this.consignment.id = 10;
this.consignment.customer = "Customer3";
this.consignment.customerList = [{ id: 1, name: "Customer1" }, { id: 2, name: "Customer2" }, { id: 3, name: "Customer3" }];
this.consignment.shipperList = [{ key: "1", value: "Shipper1" }, { key: "2", value: "Shipper2" }, { key: "3", value: "Shipper3" }];
this.consignment.consigneeList = [{ key: "1", value: "Consignee1" }, { key: "2", value: "Consignee2" }, { key: "3", value: "Consignee3" }];
this.consignment.billingList = [{ key: "1", value: "Billing1" }, { key: "2", value: "Billing2" }, { key: "3", value: "Billing3" }];
this.consignment.carrierList = [{ key: "1", value: "Carrier1" }, { key: "2", value: "Carrier2" }, { key: "3", value: "Carrier3" }];
this.get = () => {
return this.consignment;
}
}
}
class AdminHomeComponentController {
consignment: IConsignment;
selectedCustomer: any;
static $inject = ["adminHomeService"];
constructor(private adminHomeService: AdminHomeService) {
this.consignment = new Consignment();
this.consignment = this.adminHomeService.get();
this.selectedCustomer = {};
this.selectedCustomer.selected = { "name": this.consignment.customer };
}
customerAddClick(): void {
}
}
class AdminHomeComponent implements ng.IComponentOptions {
bindings: any;
controller: any;
templateUrl: string;
$routeConfig: angular.RouteDefinition[];
constructor() {
this.bindings = {
textBinding: "#",
dataBinding: "<",
functionBinding: "&"
};
this.controller = AdminHomeComponentController;
this.templateUrl = "templates/admin.home.html";
//this.$routeConfig = [
// { path: "/admin", name: "AdminHome", component: "adminHome", useAsDefault: true }
//];
}
}
angular.module("adminHome", [])
.component("adminHome", new AdminHomeComponent())
.service("adminHomeService", AdminHomeService);
This post helped me a lot: http://almerosteyn.com/2016/02/angular15-component-typescript

How to load angular1 dependencies using systemjs?

I'm using typescript, angular1 and systemjs in the following example.
The problem that I have is I'm not able to load the dependencies for the module app as in
module('app', ["ngComponentRouter", "hub"])
I see an error in the chrome dev tab that the injecting a module failed.
The System.import loads the app module which supposed to load the hub module also. But how to inject the hub module as a dependency for app module?
index.html
<app></app>
<script src="~/lib/system.js/dist/system.src.js"></script>
<script>
System.config({
defaultJSExtensions: true,
baseURL: "wwwroot",
map: {
"angular": "/lib/angular/angular.min.js",
"hub": "/App/hub.js"
}
});
System.import('./App/app');
</script>
app.ts
import * as angular from 'angular';
import * as hub from './hub/hub'
module App {
"use strict";
export class AppController {
static $inject = [
"$router"
];
constructor(private $router: any) {
$router.config([
{ path: "/hub", component: "hub", as: "Hub" },
{ path: "/home", component: "home", as: "Home" }
]);
$router.navigateByUrl("hub");
}
}
angular.
module('app', ["ngComponentRouter", "hub"]).
controller('AppController', AppController).
directive('app', () => {
return {
restrict: "E",
template: "<ng-outlet><ng-outlet>",
controller: "AppController"
}
});
}
hub.ts
export module Hub {
export class Tile {
title: string;
name: string;
constructor(title: string, name: string) {
this.name = name;
this.title = title;
}
}
export class HubController {
selectedTiles: number[];
hubTiles: Tile[];
static $inject = [
"$scope",
"$router"
];
constructor(private $scope: any, private $router: any) {
this.hubTiles = [new Tile("USA", "home"),
new Tile("Canada", "home"),
new Tile("Mexico", ""),
new Tile("India", ""),
new Tile("Germany", ""),
new Tile("Australia", "")];
this.selectedTiles = [];
$scope.$watch(() => this.selectedTiles, (newValue: number[], oldValue: number[]) => {
if (newValue[0] != oldValue[0]) {
$router.navigateByUrl(this.hubTiles[newValue[0]].name);
}
}, true);
}
}
var hub = angular.
module("hub", ["ngComponentRouter", "winjs"]).
controller("HubController", HubController).
directive("hub", () => {
return {
templateUrl: "./app/hub/hub.html",
controller: HubController,
controllerAs: "hub"
}
});
}

videogular - cuePoints not working

Recently I started learning Videogular's cue points.
My aim is to pause the video at the given time (5th second here).
Here's my angular controller:
angular.module('myApp',[
"ngSanitize",
"com.2fdevs.videogular",
"com.2fdevs.videogular.plugins.controls"
])
.controller('HomeCtrl', [
'$sce',
function ($sce) {
this.API = null;
this.onPlayerReady = function(API){
this.API = API;
};
this.init = function init(){
var timePoint = [];
var start = 5;
var end = 6;
var result = {};
result.timeLapse = {
start: start,
end: end
};
result.onLeave = function onLeave(currentTime, timeLapse, params) {
console.log('onleave');
};
result.onUpdate = function onComplete(currentTime, timeLapse, params) {
console.log('completed');
};
result.onComplete = function onUpdate(currentTime, timeLapse, params) {
console.log('update');
};
timePoint.push(result);
this.config = {
preload: "none",
sources: [
{src: $sce.trustAsResourceUrl(hv.url), type: "video/mp4"}
],
theme: {
url: "http://www.videogular.com/styles/themes/default/latest/videogular.css"
},
cuePoints: {
timePoint: timePoint
},
plugins: {
controls: {
autoHide: true,
autoHideTime: 5000
}
}
};
};
this.init();
}]
);
This controller mostly works fine, but none of the onLeave, onUpdate, onComplete callbacks work, no logs printed in console after 6 seconds.
Is there anything wrong inside my codes? Thanks.
My Angular version is 1.3.17, Videogular version is 1.2.4.
You have a working example here:
http://codepen.io/2fdevs/pen/zGJQbQ
JS:
'use strict';
angular.module('myApp', [
"ngSanitize",
"com.2fdevs.videogular"
])
.controller('HomeCtrl', [
'$sce',
function($sce) {
this.API = null;
this.onPlayerReady = function(API) {
this.API = API;
};
this.init = function init() {
var timePoint = [];
var start = 0;
var end = 6;
var result = {};
result.timeLapse = {
start: start,
end: end
};
result.onLeave = function onLeave(currentTime, timeLapse, params) {
console.log('onleave');
};
result.onUpdate = function onUpdate(currentTime, timeLapse, params) {
console.log('onUpdate');
};
result.onComplete = function onComplete(currentTime, timeLapse, params) {
console.log('onComplete');
};
timePoint.push(result);
this.config = {
preload: "none",
sources: [{
src: $sce.trustAsResourceUrl("http://static.videogular.com/assets/videos/videogular.mp4"),
type: "video/mp4"
}],
theme: {
url: "http://www.videogular.com/styles/themes/default/latest/videogular.css"
},
cuePoints: {
timePoint: timePoint
},
plugins: {
controls: {
autoHide: true,
autoHideTime: 5000
}
}
};
};
this.init();
}
]);
HTML:
<div ng-app="myApp">
<div ng-controller="HomeCtrl as controller" class="videogular-container">
<videogular vg-cue-points="controller.config.cuePoints" vg-theme="controller.config.theme.url">
<vg-media vg-src="controller.config.sources"
vg-tracks="controller.config.tracks"
vg-native-controls="true">
</vg-media>
</videogular>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-sanitize.min.js"></script>
<script src="http://static.videogular.com/scripts/videogular/latest/videogular.js"></script>
Probably you will have something wrong in the HTML.

Karma testing with .success() getting 'undefined' is not an object'

I'm trying to write a unit test to see if the 'getStudents()' provider function in my controller gets called if some properties are appropriately set. Notice the .success() callback:
$scope.update = function update() {
// omitted, just doing some checking...
// finally
else if (key.length === 3 || $scope.students.length === 0) {
StudentsProvider.getStudents($scope.keyword, $scope.selectedFilters).success(function(data) {
$scope.students = data;
});
}
};
My karma unit test looks like this:
describe("Students: Controllers", function () {
var $scope;
var ctrl;
beforeEach(module('studentsApp'));
describe("SearchCtrl", function () {
// Mock the provider
var mockStudentsProvider = {
getStudents: function getStudents() {
return [
{
Education: [],
Person: [{
ID: 1,
Name: "Testing McTestsson",
SSN: "1234567890",
Address: "Fakestreet 3", MobilePhone: "7777777"
}]
}
];
}
};
var StudentsProvider;
beforeEach(inject(function ($controller, $rootScope) {
$scope = $rootScope.$new();
ctrl = $controller('SearchCtrl', { $scope: $scope, StudentsProvider: mockStudentsProvider});
StudentsProvider = mockStudentsProvider;
}));
describe("Update", function () {
beforeEach(function () {
spyOn(StudentsProvider, 'getStudents');
});
it("should always call the provider with 3 letters", function () {
$scope.keyword = "axe";
$scope.update();
expect(StudentsProvider.getStudents).toHaveBeenCalled();
expect(StudentsProvider.getStudents).toHaveBeenCalledWith("axe", "");
});
});
});
});
When I run this, I get the following error:
TypeError: 'undefined' is not an object (evaluating 'StudentsProvider.getStudents($scope.keyword, $scope.selectedFilters).success')
and it's probably because I'm not mocking the .success() callback. How would I do that? Thanks in advance!
Replace this:
var mockStudentsProvider = {
getStudents: function getStudents() {
return [{
Education: [],
Person: [{
ID: 1,
Name: "Testing McTestsson",
SSN: "1234567890",
Address: "Fakestreet 3",
MobilePhone: "7777777"
}]
}];
}
};
with this:
var mockStudentsProvider = {
getStudents: function getStudents() {
var retVal = [{
Education: [],
Person: [{
ID: 1,
Name: "Testing McTestsson",
SSN: "1234567890",
Address: "Fakestreet 3",
MobilePhone: "7777777"
}]
}];
return {
success: function(fn) {
fn(retVal)
};
}
}
};
And replace this:
spyOn(StudentsProvider, 'getStudents');
with this:
spyOn(StudentsProvider, 'getStudents').andCallThrough();
When you do not use andCallThrough() or andCallFake() jasmine prevents execution of the method and returns null. Inside your update method you are calling null.success. This will fail. (http://jasmine.github.io/1.3/introduction.html)
In your mock method you need to change the return format--the real http method returns an object where success refers to a function which takes an input a callback function.
In your case, the callback function is:
function(data) {
$scope.students = data;
}

Resources