After few days of playing with Angular 2 Hero tutorial, I decided to play with ngUpgrade.
So I bootstrap Angular with upgradeAdapter and downgrade Angular 2 component to match Angular 1 version:
///<reference path="../node_modules/angular2/typings/browser.d.ts"/>
import {UpgradeAdapter} from "angular2/upgrade";
export const upgradeAdapter: any = new UpgradeAdapter();
import {TagFormController} from "../tags/form/TagFormController";
(function(): void {
"use strict";
upgradeAdapter.bootstrap(
document.body,
["application"],
{
strictDi: true
}
);
angular
.module("application")
.directive("tag-form", upgradeAdapter.downgradeNg2Component(TagFormController));
})();
Typescript TagFormController:
/// <reference path="../../typings/angularjs/angular.d.ts" />
///<reference path="../../custom-ts-types/custom-ts-types.ts"/>
import {Component, Input, Output, OnInit} from "angular2/core";
#Component({
selector: "tag-form",
templateUrl: "src/tags/form/tagForm.html",
})
export class TagFormController
implements IAngularComponent, OnInit {
#Input()
public articles: any[];
#Input()
public mode: string;
#Output()
public saveTag: any;
#Output()
public goToEditMode: any;
public tag: any;
#Input()
public tagId: number;
#Input()
public tagValue: number;
#Input()
public tagArticles: any[];
#Output()
public cancel: any;
constructor() {
console.log("Running");
}
public $onInit(): void {
this.tag = {
articles: this.tagArticles,
id: this.tagId,
value: this.tagValue,
};
}
public ngOnInit(): void {
this.tag = {
articles: this.tagArticles,
id: this.tagId,
value: this.tagValue,
};
}
public save(tag: any): void {
if (typeof tag.id !== "number") {
throw new TypeError("Id should be provided for tag, but is " +
typeof tag.id + " with value: " + String(tag.id));
}
console.log(tag.value);
this.saveTag({
$tag: tag
});
}
public edit(tag: any): void {
if (typeof this.cancel !== "function") {
throw new TypeError("cancel function should be provided and will be checked later!");
}
if (typeof tag.id !== "number") {
throw new TypeError("Id should be provided for tag, but is " +
typeof tag.id + " with value: " + String(tag.id));
}
this.goToEditMode({
$tag: tag
});
}
public cancelEdit(): void {
this.cancel();
}
}
console.log("I am here!");
If I look into Developer Tools in Chrome, everything should be OK, request for TagFormController is sent and I am here is displayed in console.
But usage of tagForm directive is empty inside, for me it looks like Angular does not recognize it properly. I use tagForm diretcive in this way from other tag directive:
<tag-form
*ngIf="$ctrl.tagLoaded"
[articles]="$ctrl.articles"
[mode]="$ctrl.mode"
(saveTag)="$ctrl.saveTag($tag)"
(goToEditMode)="$ctrl.goToEditMode($tag)"
[tag-id]="$ctrl.tag.id"
[tag-value]="$ctrl.tag.value"
[tagArticles]="$ctrl.tag.articles"
(cancel)="$ctrl.cancel()">
</tag-form>
I have to slightest idea what I am doing from. Maybe is important that I don't use SystemJS for Angular 1 part of project, but as I wrote request for TagFormController is sent. Can you see where I make mistake? I will be grateful if anybody help me - thank you in advance!
Perhaps you could try the following:
angular
.module("application")
.directive("tagForm", upgradeAdapter.downgradeNg2Component(TagFormController));
instead of:
angular
.module("application")
.directive("tag-form", upgradeAdapter.downgradeNg2Component(TagFormController));
Here is a working plunkr: http://plnkr.co/edit/2i46p48bTUN6jP9rTarR?p=preview.
Related
I'm fairly new to Angular and I am having some trouble finding the answer to my problem. I'm using Angular 11 with ASP.NET MVC in visual studio, and I am trying to invoke a MVC controller once a button is clicked in my app.component.html. I have looked all over the place, but all the answers are either for AngularJS or ASP.NET Core which doesn't really help me at all. Any help would be greatly appreciated.
Thanks!
app.component.html
<div style="padding-left: 140px">
<button (click)="onImportClick()" class="dv-button" style="width:
100px; padding: 4px 6px">
Import
</button>
</div>
app.component.ts
onImportClick() {
this.importErrors = [];
this.appService.callImport(4).subscribe()
this.clearFile();
//window.location.reload();
}
}
app.service.ts
export class AppService {
private baseUrl = "http://localhost:4200/";
private importUrl = this.baseUrl + 'Import/GetTest';
private test = ["test"];
myBooks: string[];
constructor(private http: HttpClient) { }
callImport(id: any) {
let body = JSON.stringify(id);
return this.http.get('Import/GetTest').pipe(map(
data => {
this.myBooks = [body];
}
)
);
}
ImportController.cs
namespace AI.Controllers.AI_API
{
public class ImportController: IController
{
public void Execute(RequestContext requestContext)
{
throw new NotImplementedException();
}
[Route("/Import/GetTest")]
public int GetTest(int id)
{
var result = id;
return result;
}
}
}
RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index"}
);
}
}
I'm facing off a classic "Not a Function" issue on Ionic Framework, I hope that you will help me to better understand this case.
I am trying to get out an object from an array. The object has private properties that I retrieve with simple getter methods.
The problem comes out when this line of the whole class above is executed:
this.selectedWorkoutPlan = this.workoutPlanList.find(object => object.getId() === this.id);
The console returns the error mentioned before.
This is my .ts file:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import {WorkoutPlanService} from "../../services/workout-plan.service";
import {WorkoutPlan} from "../../models/workout-plan";
#IonicPage()
#Component({
selector: 'page-workout-plan-detail',
templateUrl: 'workout-plan-detail.html',
})
export class WorkoutPlanDetailPage {
id: number = 0;
title: string = "";
startDate: Date = new Date();
endDate: Date = new Date();
workoutPlanList: WorkoutPlan[] = [];
selectedWorkoutPlan: WorkoutPlan = new WorkoutPlan();
constructor(public navCtrl: NavController, public navParams: NavParams,
private workoutPlanService: WorkoutPlanService) {
}
ionViewDidLoad() {
this.id = this.navParams.get("id");
this.workoutPlanList = this.workoutPlanService.getWorkoutPlanList();
this.selectedWorkoutPlan = this.workoutPlanList.find(object => object.getId() === this.id);
}
}
and this is the .ts model's class.
import {WorkoutExercise} from "./workout-exercise";
export class WorkoutPlan {
private title: string;
private exercises: WorkoutExercise[];
private startDate: Date;
private endDate: Date;
private id: number;
constructor() {
this.id = new Date().getTime();
}
setTitle(newTitle: string) {
this.title = newTitle;
}
setExercises(newExercises: WorkoutExercise[]) {
this.exercises = newExercises;
}
setStartDate(newStartDate: Date) {
this.startDate = new Date(newStartDate);
}
setEndDate(newEndDate: Date) {
this.endDate = new Date(newEndDate);
}
setId(newId: number) {
this.id = newId;
}
getTitle() {
return this.title;
}
getExercises() {
return this.exercises;
}
getStartDate() {
return this.startDate;
}
getEndDate() {
return this.endDate;
}
getId() {
return this.id;
}
}
Am I missing something in the syntax?
In my mind I thought than an array's object would have properties and methods both, isn't it?
Thanks in advance for your time.
My guess is that you might be serializing your WorkOutPlan objects somewhere within WorkoutPlanService and then parsing the strings back into WorkOutPlan objects, which causes you to lose the associated methods.
Are you stringifying those objects at any time?
I am building out an Angular 2 app using the Angular-CLI, after initially building a working version of the app using the non-CLI version of Angular 2. To my surprise, some code that wasn't a problem in my non-CLI app version HAS been a problem with my Angular-CLI version. All that said, I've resolved everything except for one final error I am stuck on.
This is the error message I'm getting:
Uncaught Error: Module build failed: Error:
/Users/fdr/Documents/rds/rds/cli-rds/src/app/ui/generate-field.component.ts
(340,48): Return type of public method from exported class has or is
using private name 'Hint'.)
And here is the problem file causing the error:
import { Component, Input, Output, EventEmitter, OnInit, AfterViewInit, ElementRef, ViewChild } from '#angular/core';
import { EventHandler } from '../app.event-handler';
import '../app.utils';
#Component({
selector: 'app-generate-field',
templateUrl: 'app/ui/generate-field.component.html',
styleUrls: ['app/ui/generate-field.component.css']
})
export class GenerateField extends EventHandler
{
public get hasFocus(): boolean
{
return this._hasFocus;
}
#Input() delay: number = 300;
#ViewChild('inputField') private inputField: ElementRef;
#ViewChild('suggestionField') private suggestionField: ElementRef;
#Input() public value: string;
#Output() private valueChange: EventEmitter<string> = new EventEmitter<string>();
#Output() public keyup: EventEmitter<KeyboardEvent> = new EventEmitter<KeyboardEvent>();
#Output() public focus = new EventEmitter<KeyboardEvent>();
#Output() public blur = new EventEmitter<KeyboardEvent>();
private inlineSuggestion: string;
private suggestions: ISuggestion[];
#Input() public options: string[];
#Output() private optionsChange: EventEmitter<string[]> = new EventEmitter<string[]>();
private isDirty: boolean = false;
private _hasFocus: boolean = false;
constructor(myElement: ElementRef)
{
super();
this.defineObservableProperty('value');
this.defineObservableProperty('isDirty');
this.defineObservableProperty('suggestions');
this.defineObservableProperty('options');
this.addPropertyListener('isDirty', function ()
{
if (this.isDirty == false)return;
var delay = this.delay ? this.delay : 500;
var self = this;
setTimeout(function ()
{
self.updateSuggestions();
this.isDirty = false;
}.bind(this), delay);
}.bind(this));
this.addPropertyListener('value', (): void=>
{
this.valueChange.emit(this.value);
this.isDirty = true;
});
this.addPropertyListener('suggestions', (): void=>
{
this.updateInlineSuggestion();
});
this.addPropertyListener('options', ()=>
{
this.optionsChange.emit(this.options);
});
}
//--------------------------------------------------------
// Functions
//--------------------------------------------------------
/**
* Evaluates value and updates the list of suggestions
*/
public updateSuggestions(): void
{
// Update suggestions
this.suggestions = this.generateSuggestions(this.value);
}
/***
* Updates the inline suggestion that appears on the text field
*/
private updateInlineSuggestion(): void
{
// Clear inline if there are no suggestions
if (this.suggestions.length == 0)
{
this.inlineSuggestion = '';
return;
}
// Show first option inline
this.inlineSuggestion = this.suggestions[0].value;
var x = this.inputField.nativeElement.selectionStart;
var y = this.inputField.nativeElement.selectionEnd;
this.suggestionField.nativeElement.selectionStart = x;
this.suggestionField.nativeElement.selectionEnd = y;
this.inputField.nativeElement.selectionStart = x;
this.inputField.nativeElement.selectionEnd = y;
this.suggestionField.nativeElement.scrollLeft = x;
}
private onFocus(): void
{
this._hasFocus = true;
// Forward event
this.focus.emit();
}
private onBlur(): void
{
this._hasFocus = false;
// Forward event
this.blur.emit();
}
interface ISuggestion
{
word: string;
match: string;
value: string;
}
try to add "export interface ISuggestion" at the last part of your code so that ISuggestion is exported, too.
Try adding : any after your method. I encountered same problem, It solved after I added any.
module ngrFilter{
'use strict';
export class UsersCtrl {
public userCollection: any[];
public userFilter: string;
constructor(){
this.userCollection = [{id:1,name:'John',surname:'Klopper'},
{id:2,name:'Mary',surname:'Schoeman'}];
}
public filterUser(user){
//The this is undefined when using as a custom filter for ng-repeat
console.log(this.userFilter)
if(user.name == this.userFilter ||
user.surname == this.userFilter){
return true;
}
}
}
angular
.module('ngrFilter',[])
.controller('UsersCtrl', UsersCtrl);
}
When using a custom filter for ng-repeat the this property is undefined in the filterUser method. Is there a way to get this filter to work or am I just doing something stupid.
I also tried adding a sample of the code here: http://fiddlesalad.com/typescript/custom-ngrepeat-filter/
Instead of a method, use a public field as filter function, which can create a closure for this.
export class UsersCtrl {
public userCollection: any[];
public userFilter: string;
public filterUser: (User) => boolean;
constructor(){
this.userCollection = [{id:1,name:'John',surname:'Klopper'},
{id:2,name:'Mary',surname:'Schoeman'}];
var self = this;
this.filterUser = function(user:User) {
return self./*...*/;
}
}
}
What you are trying to do can be done via an angular filter
For what you're trying to do I would just handle an event and rebind the list upon changing of the filter
export class UsersCtrl {
public userCollection: any[];
public filteredUserCollection: any[];
public userFilter: string;
constructor(){
this.userCollection = [{id:1,name:'John',surname:'Klopper'},
{id:2,name:'Mary',surname:'Schoeman'}];
this.filteredUserCollection = this.userCollection;
}
public filterChanged(filter){
this.filterUser(filter);
}
public filterUser(filter){
var results = [];
if(user.name == filter ||
user.surname == filter){
results.push(user);
}
this.filteredUserCollection = results;
}
}
And then your markup would change to:
<input ng-model="users.userFilter" ng-change="users.filterChanged(users.userFilter)">
<ul>
<li ng-repeat="user in users.filteredUserCollection">
{{user.name}} {{user.surname}}
</li>
</ul>
I'm new in TypeScript.
I'm getting error when trying to instantiating the class.
Below is my sample code, actual code is different can't share.
module ABC {
export class A {
public execute<T>(action: string, data?: any, callerContext?: any): IAsyncResult<T> {
// CODE::
var requestMessage = new Common.ClientClasses.ClientRequestMessage(); **// **ERROR- "WinRTError: Class not registered"****
requestMessage.requestUri = actionRequest;
requestMessage.method = "POST";
requestMessage.body = data ? JSON.stringify(data, null, 2) : null;
Common.ClientClasses.ClientRequest.executeAsync(requestMessage)
.done((result: Common.ClientClasses.ClientResponeMessage) => {
// CODE:
}
// Code::
}
}
}
declare module Common.ClientClasses {
class ClientRequestMessage {
public requestUri: string;
public method: string;
public body: string;
}
class ClientResponeMessage {
public status: number;
public statusText: string;
public responseText: string;
}
class ClientRequest {
static executeAsync(clientRequestMessage: ClientRequestMessage): any;
}
}
I did some improvements, should work:
module ABC {
export class A {
public execute<T>(action: string, data?: any, callerContext?: any) {
var requestMessage = new Common.ClientClasses.ClientRequestMessage();
requestMessage.method = "POST";
requestMessage.body = data ? JSON.stringify(data, null, 2) : null;
Common.ClientClasses.ClientRequest.executeAsync(requestMessage)
}
}
}
module Common.ClientClasses {
export class ClientRequestMessage {
public requestUri: string;
public method: string;
public body: string;
}
class ClientResponeMessage {
public status: number;
public statusText: string;
public responseText: string;
}
export class ClientRequest {
static executeAsync(clientRequestMessage: ClientRequestMessage): any {
console.log("test");
}
}
}
Then it can be run as following:
var a = new ABC.A();
a.execute("some string");
declare module creates a definition file used for Intellisense but it doesn't provide any implementation that's why I changed your code so this fragment can work.
Also if you want to use any classes from the module, you must export them so they can be visible from outside of that module.