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"}
);
}
}
Related
I have a problem and very strange behavior with autofill in Chrome. When I login and then logout from app, input fields (email, password) were autocompleted but fields looks like they are frozen and not clickable.
This bug is not every time reproduced, it happens in 1/10 cases.
I noticed on logout when fields get autocompleted, after 1 seconds font gets smaller in inputs and after that if you click on input there it seems like you are not clicking , nothing happens, but if you type some text (numbers not work, stays like frozen) input field goes as normal.
Here is gif with strange behavior:
https://gifyu.com/image/kTkX
I tried to set autocomplete="off" , but not working.
Also I matched all css clases in input fields to see is there some overriding css, but everything looks good.
<form [formGroup]="loginForm">
<input id="emailHeader" type="text" formControlName="email" placeholder="E-mail">
<input #password type="password" formControlName="password" placeholder="Lozinka">
<input type="submit" (click)="executeLogin()" value="Prijava">
</form>
I expect to fields not been frozen after autofill.
public loginForm: FormGroup;
public emailInput: ElementRef;
public passwordInput: ElementRef;
#ViewChild('email') set emailContent(content: ElementRef) {
this.emailInput = content;
}
#ViewChild('password') set passwordContent(content: ElementRef) {
this.passwordInput = content;
}
// UI helpers
public showLoginForm: boolean;
public showBalance: boolean;
public player: PlayerModel = new PlayerModel({});
public balanceInfo: BalanceInfoModel = new BalanceInfoModel({});
public nxcsBalanceInfo: NXCSBalanceInfoModel = new NXCSBalanceInfoModel({});
public dialogType = DialogType;
public customMessageError = '';
// Store
private headerState$: Observable<any>;
private loginState$: Observable<any>;
private playerState$: Observable<any>;
private emailInput$: Observable<any>;
private passwordInput$: Observable<any>;
private balanceState$: Observable<any>;
private headerSubscription: Subscription;
private loginSubscription: Subscription;
private playerSubscription: Subscription;
private emailSubscription: Subscription;
private passwordSubscription: Subscription;
private balanceSubscription: Subscription;
// tslint:disable-next-line:no-inferrable-types
private leftMenu: string = '';
// tslint:disable-next-line:no-inferrable-types
private rightMenu: string = '';
constructor(
private authService: AuthService,
private fb: FormBuilder,
private store: Store<any>,
private route: Router,
private localStorageService: LocalStorageService,
private playerService: PlayerService,
private notificationService: NotificationService,
private dialogService: DialogService,
private helpers: HelpersService,
private translateCode: TranslateCode,
private promotionService: PromotionService,
) {
this.loginForm = this.buildLoginForm();
}
ngOnInit() {
this.setupStore();
}
ngAfterViewInit() {
this.formEventsAfterViewInit();
}
ngOnDestroy() {
this.headerSubscription.unsubscribe();
this.loginSubscription.unsubscribe();
this.playerSubscription.unsubscribe();
this.notificationService.closeConnection();
}
public executeLogin() {
if(!this.loginForm.valid) {
this.customMessageError = this.translateCode.transform("EMPTY_INPUT_MESSAGE");
return;
}
this.authService.login(new LoginModel({...this.loginForm.value, details: this.helpers.sendSessionData()}))
.subscribe(
data => {
this.localStorageService.setUserAfterLogin(data.token);
this.customMessageError = '';
this.loginForm.reset();
this.route.navigate(['/app/casino']);
},
error => {
error.message.includes('Račun je zaključan') ? this.store.dispatch(new PopupNotification(error.message)) : this.customMessageError = error.message
this.addAfterErrorSubscription();
}
);
}
public openDialog(dialogType: string): void {
switch (dialogType) {
case DialogType.PAYMENT:
this.openWithdrawalDialog()
break;
case DialogType.PAYMENT_DEPOSIT:
this.checkRegistrationStep();
break;
case DialogType.TRANSACTION_HISTORY:
this.store.dispatch(new OpenDialog({
type: dialogType,
}));
break;
}
}
public openInternalTransactionsDialog(): void {
this.promotionService.getPromotionsByLocation('NXCS_DEPOSIT')
.subscribe(
data => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION, { promotions: data }),
error => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION, { promotions: []}),
);
}
public backToRegistrationStep() : void {
switch (this.player.registrationStep) {
case 1 : this.route.navigate(['/auth/registration/step-two']);
break;
case 2 : this.route.navigate(['/auth/registration/step-three']);
break;
case 3 : this.route.navigate(['/auth/registration/step-four']);
break;
case 4 : this.route.navigate(['/auth/registration/step-five']);
break;
case 5 : this.route.navigate(['/auth/registration/step-six']);
break;
default : this.route.navigate(['/login']);
break;
}
}
public toggleMenu(dialog): void {
if (dialog === 'left') {
this.leftMenu = this.leftMenu === dialog ? '' : dialog;
}
if (dialog === 'right') {
this.rightMenu = this.rightMenu === dialog ? '' : dialog;
}
this.dispatchShadow();
}
private openWithdrawalDialog(_data: any = {}): void {
const playerRole = this.localStorageService.getPlayer()['profileRole'];
if (playerRole === 'WITHDRAWAL_DISABLED' && this.player.uploadedAdditionalInfo) {
this.store.dispatch(new OpenNotification({ type: NotificationType.WITHDRAWAL_DISABLED }));
return;
}
playerRole === 'WITHDRAWAL_DISABLED' ?
this.store.dispatch(new OpenNotification({type: NotificationType.MONEY_LAUNDERING})) :
this.dialogService.openDialog(MENU_DIALOGS.WHITDRAWALS, _data);
}
private openProceedToRegistration(): void {
this.store.dispatch(new OpenNotification ({type: NotificationType.PROCEED_REGISTRATION}))
}
private checkRegistrationStep(): void {
if(this.player.registrationStep < 6) {
this.openProceedToRegistration();
} else {
this.dialogService.openDialog(MENU_DIALOGS.DEPOSITS, {});
}
}
private dispatchShadow(): void {
if (this.leftMenu !== '') {
this.store.dispatch(new OpenedLeftMenu());
this.leftMenu = '';
}
if (this.rightMenu !== '') {
this.store.dispatch(new OpenedRightMenu());
this.rightMenu = '';
}
}
private buildLoginForm(): FormGroup {
return this.fb.group({
email: [
'', Validators.compose([Validators.required, Validators.min(5)]),
],
password: [
'', Validators.compose([Validators.required, Validators.min(5)])
],
});
}
private loadBalance(): void {
this.playerService.getPlayerBalance().toPromise()
.then(data => this.store.dispatch(new SetPlayerBalance({balanceInfo: new BalanceInfoModel(data) })))
.then(() => {
if (this.player.externalId) {
this.playerService.getNXCSPlayerBalance()
.subscribe(
data => this.store.dispatch(new SetPlayerNXCSBalance({ nxcsBalanceInfo: new NXCSBalanceInfoModel(data) })),
error => console.log(error),
);
}
});
}
// Store methods
private setupStore(): void {
this.headerState$ = this.store.pipe(select('headerStore'));
this.loginState$ = this.store.pipe(select('loginStore'));
this.playerState$ = this.store.pipe(select('playerStore'));
this.balanceState$ = this.store.pipe(select('balanceStore'));
this.addSubscriptions();
}
private formEventsAfterViewInit(): void {
if (this.emailInput && this.passwordInput) {
this.emailInput$ = fromEvent(this.emailInput.nativeElement, 'focus');
this.passwordInput$ = fromEvent(this.passwordInput.nativeElement, 'focus');
this.addFormEventsSubscriptions();
}
}
private addFormEventsSubscriptions(): void {
this.emailSubscription = this.emailInput$.subscribe(() => this.triggerEmailFocus());
this.passwordSubscription = this.passwordInput$.subscribe(() => this.triggerPasswordFocus());
}
private triggerEmailFocus(): void {
this.emailInput.nativeElement.select();
if (this.emailSubscription) {
this.emailSubscription.unsubscribe();
}
}
private triggerPasswordFocus(): void {
this.passwordInput.nativeElement.select();
if (this.passwordSubscription) {
this.passwordSubscription.unsubscribe();
}
}
private addSubscriptions(): void {
this.addHeaderSubscription();
this.addLoginSubscription();
this.addPlayerSubscription();
this.setBalanceSubscription();
}
private addHeaderSubscription(): void {
this.headerSubscription = this.headerState$
.subscribe(headerState => this.showLoginForm = headerState !== HeaderActionTypes.LoginPage);
}
private addLoginSubscription(): void {
this.loginSubscription = this.loginState$
.subscribe(loginState => {
if (loginState) {
this.loadBalance();
this.notificationService.connect(localStorage.getItem('token'));
} else {
this.notificationService.closeConnection();
}
this.showBalance = loginState;
this.formEventsAfterViewInit();
});
}
private addPlayerSubscription(): void {
this.playerSubscription = this.playerState$
.subscribe(playerData => this.player = playerData);
}
private addAfterErrorSubscription(): void {
this.passwordSubscription = this.passwordInput$.subscribe(() => {
if (this.customMessageError !== '') {
this.customMessageError = '';
this.passwordSubscription.unsubscribe();
}
});
}
}
I was facing the same issue in Angular and found a workaround for this scenario, resetting the input field's value on input click seems to fix the locking issue for me.
HTML:
<input (click)="unfreezeInput($event)">
TS:
unfreezeInput(el) {
// setting input value again makes it editable
el.target.value = el.target.value;
}
This is an issue that happens every time Google Chrome autofills the fields when you permit it to save your login credentials on any form. It bugged me out the first times as well.
I tried giving it a shot or two back when I encountered it for the first, but I gradually moved on and accepted it as a not-a-big deal kinda bug that every chrome user gotta have to deal with.
So in conclusion, it's got nothing to do with your code. If you want to unfreeze the input fields, start typing something in them to change their value.
I hope, this helps you and your nerves in accepting this browser-related behavior.
Have you tried using the a href tag? I know it's an obvious thing, but sometimes we forget to do things like that. Also, you can use the a:hover tag in your CSS.
I need to start Index from Controller before opening page and that was working but when i added RoutePrefix controller didn't want to start. What should be done so i can start controller even with RoutePrefix.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller = "main", id = RouteParameter.Optional }
);
}
}
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Main", action = "Index", id = UrlParameter.Optional }
);
}
}
[RoutePrefix("api/main")]
public class MainController : ApiController
{
private static List<Korisnik> adminlist = new List<Korisnik>();
private static List<Vozac> vozaclist = new List<Vozac>();
private static List<Korisnik> korisniklist = new List<Korisnik>();
[HttpGet, Route("")]
public RedirectResult Index()
{
ReadFromXML(Enums.Uloga.Dispecer);
var requestUri = Request.RequestUri;
return Redirect(requestUri.AbsoluteUri + "Content/index.html");
}
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.
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 am setting up a small angularjs app inside a Sharepoint web part. This is the first time doing this, but I made a demo work in this setting before doing the proper code. My problem now is that I think everything is properly hooked up, but the Controller constructor is never called? I am aware that the code is not complete, but at the very least I should enter the constructor and call the service. The only alerts I see are the ones in the App file. Here are the different files:
HTML:
<div id="bidragsoplysninger2015App">
<div data-ng-controller="bidragsoplysninger2015Controller">
<div id="template-content" ng-include="'/AngularJS/Views/Bidragsoplysninger2015.html'"></div>
</div>
Partial:
<ul>
<li data-ng-repeat="indbetaling in indbetalinger | orderBy:'registreringsdato'">{{indbetaling.registreringsdato}} - {{indbetaling.beloeb}}</li>
</ul>
Model:
class Indbetaling {
constructor(
public beloeb: number,
public betalingsform: string,
public fagkode: string,
public indskudstype: string,
public institutionsNr: string,
public kundeNr: number,
public ordningNr: number,
public pensionsform: string,
public pensionsmodel: string,
public registreringsdato: Date,
public valoerMaaned: string
) {}
}
Interface:
interface IIndbetalinger {
getIndbetalinger(cpr: string): Indbetaling[]
}
Service:
class Bidragsoplysninger2015Service implements IIndbetalinger
{
private scope: any;
private http: any;
constructor($scope: ng.IScope, $http: ng.IHttpService) {
this.scope = $scope;
this.http = $http;
}
getIndbetalinger(cpr: string): Indbetaling[]
{
var promise = this.http.get('/_layouts/wpgenerelportal/Indbetalinger.aspx/GetIndbetalinger?cpr=' + cpr);
promise = promise.then(this.mapIndbetalinger).then(response => response.data);
return promise;
}
mapIndbetalinger(data) {
alert("Mapping!");
}
}
Controller:
class Bidragsoplysninger2015Controller {
private indbetalinger: Indbetaling[];
public static $inject = [
'$scope',
'bidragsoplysninger2015Service'
];
constructor(private $scope, private bidragsoplysninger2015Service: IIndbetalinger) {
alert("Controller constructor");
this.indbetalinger = $scope.indbetalinger = bidragsoplysninger2015Service.getIndbetalinger("110680-3419");
// 'vm' stands for 'view model'. We're adding a reference to the controller to the scope
// for its methods to be accessible from view / HTML
$scope.vm = this;
}
}
App:
alert("In app 1");
var bidragsoplysninger2015AppModule = angular.module('bidragsoplysninger2015App', []);
bidragsoplysninger2015AppModule.service("bidragsoplysninger2015Service", Bidragsoplysninger2015Service);
bidragsoplysninger2015AppModule.controller("bidragsoplysninger2015Controller", Bidragsoplysninger2015Controller);
alert("In app 2");
$(document).ready(() => {
alert("In app 3");
angular.bootstrap($("#bidragsoplysninger2015App"), ['bidragsoplysninger2015App']);
});
I found the problem buried in this post: 'unknown provider error' in Angular app
The sentence: "Services don't have $scope" was the key. Once I removed the $scope as an input parameter to the service constructor, everything worked.