我正在使用 Angular 2.0 稳定版本,并希望用户在离开页面之前进行确认(他们的更改不会被保存)。
问题是,如果用户希望访问延迟加载的页面,则实现的“CanDeactivate”防护会被调用两次。(使用哈希位置策略)
重现步骤:
应用程序路由.ts
{ path: 'task1', component: Task1Component, canDeactivate: ['candeactivate'] },
Run Code Online (Sandbox Code Playgroud)
应用程序/task-1/task1.module.ts
@NgModule({
imports: [CommonModule],
declarations: [Task1Component],
exports: [Task1Component],
providers: [
{
provide: 'candeactivate',
useValue: () => {
console.log("can deactivate");
return confirm("Test");
}
}
]
})
export class Task1Module {}
Run Code Online (Sandbox Code Playgroud)
请注意,系统会要求您两次确认。我找到了https://github.com/angular/angular/issues/11754,但目前没有任何解决方案。
有什么解决方法吗?
我目前正在阅读Angular 2 教程并学习如何使用带参数的路由器通过id获取对象数据.
以下是用于参考我将要问的问题的代码.
以下是app.module.ts基于id指向组件的路径定义
{
path:'detail/:id',
component:HeroDetailComponent
}
Run Code Online (Sandbox Code Playgroud)
服务方法(来自Service类),用于根据id获取数据
getHero(id: number): Promise<Hero> {
return this.getHeroes()
.then(heroes => heroes.find(hero => hero.id === id));
}
Run Code Online (Sandbox Code Playgroud)
用于从网址中提取信息的构造函数和OnInit方法(来自显示数据的hero-details.component)
constructor(
private heroService: HeroService,
private route: ActivatedRoute,
private location: Location
){}
ngOnInit():void{
this.route.params
.switchMap((params:Params) => this.heroService.getHero(+params['id'])
.subscribe(hero => this.hero = hero));
}
Run Code Online (Sandbox Code Playgroud)
最后是我们提取的数据的例子.id是类型编号和名称类型字符串.
{ id: 11, name: 'Mr. Nice' }
Run Code Online (Sandbox Code Playgroud)
问:内ngOnInit我们从一个字符串转换将ID号的参数范围内this.heroService.getHero()调用.+params['id']转换方面的工作究竟如何?我的猜测是,这是由于我们在app.module.ts文件中布置路线的方式,这detail/:id相当于params['id']但我希望有一个明确的探索,以便我知道我将来会做些什么.谢谢
这是一个可以玩的玩家:
https://plnkr.co/edit/qTjftING3Hk2fwN36bQa?p=preview
一切都运行良好,除非您手动更改网址栏中的id参数,因为项目下拉列表不会将新projectId显示为当前项目.当用户将网址保存为收藏链接并将其复制/粘贴到网址栏时,会发生这种情况!我会说一个常见的情况!
为了解决这个问题,我可以收听route.params中的更改TestsListComponent并添加一个检查,sharedService/EventEmitter其中更改的ID存在于该下拉列表中.TestsListComponent中的bool返回值existsProjectId决定我应该重定向到/projects页面,因为id不存在.
但老实说,TestsListComponent至少从用户体验的角度来看,重定向是太迟了,因为route projects/:id/tests它已经被激活了.
你会如何解决这种不端行为?
PS
也许有一种全局参数更改我可以听,并检查ProjectsListComponent中的路径及其ID,这将有所帮助!
如果有人知道如何在窗口模式下编辑plunkr的url栏来测试这种不一致性,请告诉我你是如何使readonly url bar可编辑的...即使将url复制到新的选项卡也不行,因为我得到了一个plunkr找不到错误... => 答案
我正在进行登录检查.一旦成功,我想将用户重定向到同一应用程序中的另一个页面.我有以下代码来做到这一点.
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { DataService } from '../services/data.service';
import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
providers: [Location, {provide: LocationStrategy, useClass: PathLocationStrategy}],
styleUrls: ['./login.component.css'],
})
export class LoginComponent {
static location:Location;
constructor(private formBuilder: FormBuilder,
private dataService: DataService,location: Location) {
LoginComponent.location = location;
this.loginForm = this.formBuilder.group({
username: this.username,
password: this.password
});
}
loginForm : FormGroup;
username = new FormControl('', Validators.required);
password = new FormControl('', …Run Code Online (Sandbox Code Playgroud) 我有一个页面,我有一张桌子.有一列名为"Actions".
一旦用户单击任何行中的action-column,操作菜单将显示Edit和Delete.一旦用户点击编辑,我就会重定向到另一个html页面.
一切都很好.但重定向到另一个页面后,菜单不会消失.如果我返回并再次单击操作列,则会出现带有编辑和删除的新菜单.
<p-dataTable #dataTable>
<p-column field="" header="{{l('Actions')}}" [sortable]="false" [style]="{'width':'25px'}">
<ng-template let-record="rowData" pTemplate="body">
<div class="btn-group dropdown" normalizePosition>
<button class="dropdown-toggle btn btn-xs btn-primary blue"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
<i class="fa fa-cog"></i>
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>
<a (click)="onEditClick(record, $event)">{{ l('Edit') }}</a>
</li>
<li>
<a (click)="onDeleteClick(record, $event)">{{ l('Delete') }}</a>
</li>
</ul>
</div>
</ng-template>
</p-column>
</p-dataTable>
onEditClick(selectedValue: any): void {
this.router.navigate(['/app/xyz/pqr', selectedClassification.id]);
}
Run Code Online (Sandbox Code Playgroud) [ts]无法找到模块'@ angular/core'.
[ts]无法找到模块'@ angular/router'.
import {Component, ElementRef, Input,Output,EventEmitter,Inject, OnInit,ViewChild} from '@angular/core';
import {KendoGridComponent} from '../grid/grid.component'
import { Router} from '@angular/router';
Run Code Online (Sandbox Code Playgroud)
{
"name": "SPORTS",
"version": "1.0.0",
"description": "SPORTS player - v0.2.37.1",
"engines": {
"node": "7.10.1"
},
"license": "ISC",
"dependencies": {
"@angular/animations": "^5.2.2",
"@angular/common": "^5.2.2",
"@angular/compiler": "^5.2.2",
"@angular/compiler-cli": "^5.2.2",
"@angular/core": "^5.2.2",
"@angular/forms": "^5.2.2",
"@angular/http": "^5.2.2",
"@angular/platform-browser": "^5.2.2",
"@angular/platform-browser-dynamic": "^5.2.2",
"@angular/platform-server": "^5.2.2",
"@angular/router": "^5.2.2",
"@angular/upgrade": "2.0.0",
"@ng-idle/core": "2.0.0-beta.2",
"@ng-idle/keepalive": "2.0.0-beta.2",
"@types/jquery": "^3.2.10", …Run Code Online (Sandbox Code Playgroud) 我有一个从 ActivatedRoute 的 params 属性获取值的组件。
组件看起来像:
......
constructor(public userRegistration: UserRegistrationService, public userLogin: UserLoginService,
public router: Router, public route: ActivatedRoute) {
}
ngOnInit() {
this.verificationCode = new FormControl('', [Validators.required]);
this.confirmationCodeForm = new FormGroup({verificationCode: this.verificationCode});
//******************************
this.sub = this.route.params.subscribe(params => {
this.email = params['userId'];
});
//******************************
this.errorMessage = null;
}
......
Run Code Online (Sandbox Code Playgroud)
该测试提供了一个 ActivatedRoute 作为模拟该类的“useValue”。测试看起来像:
describe('ConfirmRegistrationComponent', () => {
let component: ConfirmRegistrationComponent;
let fixture: ComponentFixture<ConfirmRegistrationComponent>;
let userRegistrationService: UserRegistrationService;
let userLoginService: UserLoginService;
let router: Router;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, FormsModule, RouterTestingModule, HttpClientModule], …Run Code Online (Sandbox Code Playgroud) 我有以下路由应该路由到同一个组件,我可以通过使用以下结构来让它工作。
const carModuleRoutes: Routes = [
{ path: 'car/:category/:carId', component: CarDetailComponent},
{ path: 'car/:carId', component: CarDetailComponent},
];
Run Code Online (Sandbox Code Playgroud)
但我知道这不是这样做的标准方法,是否有执行相同功能的正确方法?
如果我从一个页面导航到另一个页面并多次返回,我可以通过硬件或浏览器后退按钮浏览整个路由器历史记录.
我想实现硬件后退按钮将我带到与ion-back-button工具栏中相同的页面.
例
第1页>第2页>第3页
我从第1 页导航到第2页.然后我从第2 页导航到第3页并ion-back-button多次返回.如果我然后按下硬件/浏览器后退按钮,我会再次进入第2 页和第3页.相反,如果我在第2页上按下它,我希望硬件/浏览器后退按钮导航到第1 页.
我遇到了 Angular 的情况,其中路由数据解析器似乎准备正确返回数据,但解析从未发生。这特别奇怪,因为我有另一个组件的平行排列,并且在那里工作正常。
该应用程序通过 HTTP 检索有关一系列事件的数据。在 中EventListComponent,解析器返回所有事件以响应/events,并且组件正确显示它们。在一个EventDetails组件中,在我目前的安排中,我仍然通过 HTTP 检索所有事件,然后在解析器中响应/events/[the event ID],选择应该显示其详细信息的事件。(这是来自 Pluralsight Angular Fundamentals 课程,以防它听起来很熟悉。但我倾向于观看视频,然后按照我自己的顺序完成它们,以尝试巩固我头脑中的技能。)
远程事件.service.ts
import { Injectable, EventEmitter } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { IEvent } from './event.model';
@Injectable()
export class RemoteEventService {
constructor(
private http: HttpClient
) {}
getEvents(): Observable<IEvent[]> {
return this.http.get<IEvent[]>('/api/ngfdata/events.json');
}
getEventById(id: number): Observable<IEvent> {
console.log(`In getEventById: id = ${id}`);
const emitter = new EventEmitter<IEvent>(); …Run Code Online (Sandbox Code Playgroud) angular ×10
angular2-routing ×10
typescript ×3
angular5 ×1
html ×1
ionic4 ×1
javascript ×1
npm ×1
resolve ×1
routing ×1