【angular5项目积累总结】优秀组件以及应用实例
1.手机端 图片预览组件
组件:sideshow
效果图:(预览图全屏 且可以左右移动)

code:
<div class="row ui-app-screenshot">
<img src="{{proUrl(pic.Url)}}" *ngFor="let pic of currApp.Pictures;let i = index;" (click)="onViewPicture(i)">
</div>
<slideshow [imageUrls]="slideUrls" [showArrows]="false" #slideRef (click)="onCloseViewPicture()"></slideshow>
import { ViewChild, Component, ElementRef, Renderer2 } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { AppStoreService } from '../../service/appService';
import { ConfigureOptions } from '../../configure/configure.options';
import { BrowserService } from '../../service/browser.service';
import { Adal4Service } from '../../adal/adal4.service';
@Component({
selector: 'mobile-app-info',
templateUrl: './mobileAppInfo.html',
styleUrls: ['./mobileAppInfo.css']
})
export class MobileAppInfo {
@ViewChild('slideRef') slideRef: ElementRef;
constructor(
private router: Router,
private actRouter: ActivatedRoute,
private appService: AppStoreService,
private browserService: BrowserService,
private appOptions: ConfigureOptions,
private renderer: Renderer2,
private adalService: Adal4Service) {
}
id: string;
platSource: any;
showRateBox: boolean = false;
rateVal: number = 0;
screenHeight: any;
currApp: any = [];
currPackage: any = [];
userRateStars: any = [{}, {}, {}, {}, {}];
slideUrls: any = [{}];
eleSlidershow: any;
username: string;
ngOnInit(): void {
this.initWinHeight();
this.eleSlidershow = this.slideRef && this.slideRef['container'].nativeElement;
if (this.eleSlidershow) {
this.renderer.setStyle(this.eleSlidershow, 'position', 'fixed');
this.renderer.setStyle(this.eleSlidershow, 'top', '0');
this.renderer.setStyle(this.eleSlidershow, 'z-index', '1041');
this.renderer.setStyle(this.eleSlidershow, 'display', 'none');
}
this.actRouter.params.subscribe((params: Params) => {
this.id = params["id"];
this.platSource = this.browserService.getBrowserInfo();
if (!this.platSource.isMobile && !this.platSource.isWechat) {
this.router.navigate(["/appInfo/" + this.id], {});
}
this.appService.GetAppInfo(this.id, (rtv) => {
this.initAppData(rtv);
});
});
this.username = this.adalService.userInfo.username || "未登录";
}
initAppData(rtv: any) {
this.currApp.IconUrl = this.proUrl(rtv.IconUrl);
this.currApp.Name = rtv.Name || '';
this.currApp.DownloadCount = rtv.DownloadCount || 0;
this.currApp.AvgScore = rtv.AvgScore || 0;
this.currApp.ScoreCount = rtv.ScoreCount || 0;
this.currApp.Pictures = rtv.Pictures || [];
this.currApp.CreatedOn = rtv.CreatedOn || '';
this.currApp.Category = rtv.Category || '';
this.currApp.Version = rtv.Version || '';
this.currApp.IsScored = rtv.IsScored || false;
this.currApp.Description = this.proTxt(rtv.Description);
this.currApp.scoreTxt = rtv.IsScored ? '已评分' : '评 分';
this.slideUrls = rtv.Pictures.map(p => this.proUrl(p.Url));
if (this.slideUrls.length == 0) {
this.slideUrls.push({});
}
this.slideRef['slideIndex'] = this.slideUrls.length - 1;
let _pkgArray = this.platSource.platform.Android ? rtv.AndoridPackages[0] : rtv.iOSPackages[0];
this.currPackage.Version = _pkgArray && _pkgArray.Version || '';
this.currPackage.ReleaseNotes = this.proTxt(_pkgArray && _pkgArray.ReleaseNotes);
this.currPackage.FileSize = this.proSize(_pkgArray && _pkgArray.FileSize || 0);
}
initWinHeight() {
this.screenHeight = (window.screen.height || window.innerHeight) - 52;
let self = this;
window.addEventListener("resize", function () {
self.screenHeight = (window.screen.height || window.innerHeight) - 52;
});
}
proUrl(url) {
return this.appOptions.BlobUrl + url;
}
proDevice() {
let devStr = '';
if (this.platSource.platform.Android) {
this.currPackage ? devStr = 'Android' : devStr = '不支持Android';
} else if (this.platSource.platform.iPad || this.platSource.platform.iPhone) {
this.currPackage ? devStr = 'IOS' : devStr = '不支持IOS';
}
return devStr;
}
proTxt(txt: string) {
return txt ? txt.replace(/\r?\n/g, "<br />").replace('undefined', '<font color="#a1a1a1">暂无信息</font>') : '<font color="#a1a1a1">暂无信息</font>';
}
proSize(limit: any) {
var size = "";
if (!limit) return size;
if (limit < 0.1 * 1024) { //如果小于0.1KB转化成B
size = limit.toFixed(2) + "B";
} else if (limit < 0.1 * 1024 * 1024) {//如果小于0.1MB转化成KB
size = (limit / 1024).toFixed(2) + "KB";
} else if (limit < 0.1 * 1024 * 1024 * 1024) { //如果小于0.1GB转化成MB
size = (limit / (1024 * 1024)).toFixed(2) + "MB";
} else { //其他转化成GB
size = (limit / (1024 * 1024 * 1024)).toFixed(2) + "GB";
}
var sizestr = size + "";
var len = sizestr.indexOf("\.");
var dec = sizestr.substr(len + 1, 2);
if (dec == "00") {//当小数点后为00时 去掉小数部分
return sizestr.substring(0, len) + sizestr.substr(len + 3, 2);
}
return sizestr;
}
getStarClass(val: number): number {
return Math.floor(val * 2) || 0;
}
onOpenRate() {
if (this.checkAuth()) {
this.showRateBox = true;
this.rateVal = 0;
}
}
onCloseRate() {
this.showRateBox = false;
}
onSetScore() {
this.appService.SetScore(this.id, this.rateVal, (rtv) => {
this.currApp.IsScored = true;
this.onCloseRate()
});
}
onRate(value): void {
this.rateVal = value;
}
getDownloadUrl(): void {
if (!this.checkAuth()) {
return;
}
this.appService.GetDownloadUrl(this.id, this.platSource.platform.Android ? "Android" : "iOS", (ret) => {
if (!!ret) {
window.location.href = ret;
} else {
alert("获取下载地址失败,请稍后再试");
}
});
}
private checkAuth(): boolean {
var user = this.adalService.userInfo;
if (user.authenticated) {
return true;
}
localStorage.setItem("app-store-redirect-uri", window.location.pathname);
this.router.navigate(["/login"], {});
return false;
}
onViewPicture(index: any): void {
this.renderer.setStyle(this.eleSlidershow, 'display', 'block');
this.slideRef && this.slideRef['onButtonClick'].call(this.slideRef, index || 0);
}
onCloseViewPicture(): void {
this.renderer.setStyle(this.eleSlidershow, 'display', 'none');
}
}
2.树形组件或者树形下拉框组件
ng2tree ngx-treeview
地址:https://github.com/leovo2708/ngx-treeview
angular2-tree
2.1 难点:ng2tree 异步加载
预览:

code:
<tree [tree] ="orgTree" [settings]="{rootIsVisible: false}" (nodeSelected)="logEvent($event)" (nodeMoved)="onNodeMoved($event)"></tree>
import { Component } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { TreeModel, NodeEvent, TreeModelSettings } from 'ng2-tree';
import { UserService } from '../common/userService';
import { CommonService } from '../../providers/commonService';
@Component({
selector: 'orgTree',
templateUrl: './orgTree.html',
styleUrls: ['./orgTree.css']
})
export class orgTree {
menuItems: any = [
{ title: "添加", icon: "#FxSymbol0-0bd", event: this.onAdd.bind(this) },
{ title: "编辑", icon: "#FxSymbol0-0bf", event: this.onEdit.bind(this) }
]
public orgTree: TreeModel;
public nodeTree: Array<TreeModel> = [];
constructor(
private router: Router,
private actRouter: ActivatedRoute,
private comService: CommonService,
private userService: UserService) {
this.onRefresh(comService);
}
loadNodes(id: string,callback:any):void {
let rtv: Array<TreeModel> = [];
this.userService.LoadSyncTree(id, (result) => {
let length: number = result.children.length;
if (length > 0) {
for (let i = 0; i < length; i++) {
let node: TreeModel =
{
id: result.children[i].id,
value: result.children[i].value,
loadChildren: (cb) => {this.loadNodes(result.children[i].id,cb)
}
}
rtv.push(node);
}
}
callback(rtv);
});
}
currGroup: string = '';
groupId: string = '';
ngOnInit(): void {
this.actRouter.params.subscribe((params: Params) => {
this.groupId = params["id"];
if (!this.groupId) {
this.groupId = "org";
}
this.currGroup = params["id"];
this.onLoadTree(this.groupId);
});
}
public logEvent(e: NodeEvent): void {
if (e.node.id.toString() == '') {
alert('根机构不可编辑!')
} else {
this.currGroup = e.node.id.toString();
if (this.currGroup != "") {
this.router.navigate(['/ou/org/' + this.currGroup + '/member'], {});
}
}
}
onLoadTree(id: string) {
this.userService.LoadSyncTree(null, (result) => {
const treeSettings: TreeModelSettings = {
static: false,
rightMenu: false,
leftMenu: false,
isCollapsedOnInit: false
}
let length: number = result.children.length;
for (let i = 0; i < length; i++) {
result.children[i].loadChildren = (callback) => {this.loadNodes(result.children[i].id,callback)
}
};
this.orgTree = result;
this.orgTree.settings = treeSettings;
});
}
onEdit() {
if (this.currGroup == '' || this.currGroup == null) {
alert('请先选择一个机构再进行编辑操作。');
}
else
this.router.navigate(['/ou/' + this.groupId + '/' + this.currGroup + '/edit'], {});
}
onAdd() {
if (this.currGroup == '' || this.currGroup == null) {
alert('请先选择一个机构再进行添加操作。');
} else
this.router.navigate(['/ou/' + this.groupId + '/' + this.currGroup + '/create'], {});
}
onOUFresh() {
this.userService.RefreshTree(this.groupId, (result) => {
const treeSettings: TreeModelSettings = {
static: false,
rightMenu: false,
leftMenu: false,
isCollapsedOnInit: false
}
this.orgTree = result;
this.orgTree.settings = treeSettings;
});
}
onClose() {
this.router.navigate(['/ou']);
}
onRefresh(comService: CommonService) {
this.comService.notifyObservable$.subscribe(data => {
if (data == 'refreshOrgTree') {
this.currGroup = '';
this.onLoadTree(this.groupId);
}
}, error => {
console.log(`subscribe error:${error}`)
})
}
onNodeMoved(e: NodeEvent): void {
console.log("curr:" + e.node.parent.value);
console.log(e.node.value);
}
}
2.2 改造:下拉框 tree
预览:

3. 上传组件
组件:ng2-file-upload
code:
<input type="file" ng2FileSelect [uploader]="uploader" [(ngModel)]="fileInfo"/>
import { Component } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { FileUploader, FileItem, ParsedResponseHeaders } from 'ng2-file-upload';
import { Adal4Service } from '../../adal/adal4.service';
import { ConfigureService } from '../../configure/configure.service';
import { UserService } from '../common/userService';
@Component({
selector: 'usersimport',
templateUrl: './importUsers.html',
styleUrls: ['./importUsers.css']
})
export class importUsers {
errorMsg: string;
lstHistory: any;
template: string;
token: string;
uploader: FileUploader = null;
parentUrl: string;
fileInfo: string;
groupId: string;
orgPath: string;
menuItems: any = [
{ title: "刷新", icon: "#FxSymbol0-0bf", event: this.onRefresh.bind(this) }
]
constructor(
private router: Router,
private actRouter: ActivatedRoute,
public configService: ConfigureService,
private adal4Service: Adal4Service,
private userService: UserService
) {
this.template = "/api/import/template?type=user";
this.token = this.adal4Service.userInfo.token;
this.uploader = new FileUploader({
url: "/api/Import/User",
method: "POST",
itemAlias: "dataFile",
autoUpload: false,
headers: [{ name: 'Authorization', value: `Bearer ${this.token}` }]
});
this.menuItems = [
{ title: "上传", icon: "#FxSymbol0-001", event: this.uploadExcel.bind(this) },
{ title: "刷新", icon: "#FxSymbol0-0bf", event: this.onRefresh.bind(this) }
];
this.onRefresh();
}
onRefresh(): void {
this.userService.RefreshHistory("ImportUser", (rtv) => {
this.lstHistory = rtv;
});
}
ngOnInit(): void {
this.parentUrl = this.router.url;
this.actRouter.params.subscribe((params: Params) => {
this.groupId = params["groupId"] || this.groupId;
this.groupId && this.initOrgPath();
});
}
onClose() {
this.router.navigate(['/ou/org/' + this.groupId + '/member/'], {});
}
uploadExcel() {
if (this.uploader != null && this.uploader.queue[0] != null) {
this.uploader.queue[0].onSuccess = (response, status, headers) => {
if (status == 200) {
this.errorMsg = "";
let rtv = JSON.parse(response);
if (rtv.RetCode == 0) {
this.errorMsg = "文件上传成功,结果查看结果列表。";
} else {
this.errorMsg = "文件上传失败." + rtv.RetMessage;
}
} else {
this.errorMsg = response;
}
this.fileInfo = "";
};
this.uploader.onBeforeUploadItem = (item) => {
item.withCredentials = false;
}
this.uploader.onSuccessItem = this.onSuccessItem.bind(this);
this.uploader.onErrorItem = this.onErrorItem.bind(this);
this.uploader.uploadAll();
}
else {
alert('请选择上传文件!');
}
}
onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
if (status != 200) {
alert('导入人员失败!');
} else {
alert(response);
}
this.fileInfo = "";
this.onClose();
}
onSuccessItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
if (status == 200) {
this.errorMsg = "";
let rtv = JSON.parse(response);
if (rtv.status == 1) {
alert('文件上传成功!');
} else {
alert('文件上传失败,错误信息:' + rtv.message);
}
this.fileInfo = "";
this.uploader.removeFromQueue(item);
this.uploader.clearQueue();
this.uploader.destroy();
this.onRefresh();
} else {
alert(response);
}
this.onClose();
}
initOrgPath() {
let _array = decodeURIComponent(this.groupId).split(',');
if (_array && _array.length > 0) {
this.orgPath = _array.map(o => o.replace('OU=', '')).reverse().join('#');
if(this.orgPath) this.orgPath = decodeURIComponent(this.orgPath);
}
}
}
2.头像上传 编辑图片组件
angular2-img-cropper
3.日期选择
https://github.com/CuppaLabs/angular2-datetimepicker
4.列表分页组件
npm install ngx-pagination
5.html 编辑器
npm install angular-froala-wysiwyg --save
https://summernote.org/
https://github.com/lula/ngx-summernote/
推荐组件库:
FreeNG
https://freengs.github.io/#/main/introduction
http://www.wheelsfactory.cn
https://www.jqwidgets.com/angular/#demos/angular2/angular-fileupload-defaultfunctionality.htm
https://www.telerik.com/kendo-angular-ui/components/
https://www.infragistics.com/angularsite/components/grids_and_lists.html
https://docs.nativescript.org/angular/ui/ng-ui-widgets/date-picker
https://material.angular.io/components/datepicker/examples
https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RecordPaging/jQuery/Light/
https://akveo.github.io/ngx-admin/?utm_source=github&utm_medium=ngx_admin_readme&utm_campaign=themes
未完待续,本文章待补充....
【angular5项目积累总结】优秀组件以及应用实例的更多相关文章
- 【angular5项目积累总结】avatar组件
View Code import { Component, HostListener, ElementRef } from '@angular/core'; import { Adal4Service ...
- 【angular5项目积累总结】breadcrumb面包屑组件
view code <div class="fxs-breadcrumb-wrapper" aria-label="Navigation history" ...
- 【angular5项目积累总结】panel组件
view code panel.component.css :host { display:flex; min-width:300px } panel.component.html <heade ...
- 【angular5项目积累总结】遇到的一些问题以及解决办法
1.项目中字符串特别是\r\n,替换成br之后,在页面换行无法生效? 答:绑定元素 innerHTML. <div class="panel-body" [innerHTML ...
- 【angular5项目积累总结】消息订阅服务
code import { Injectable } from '@angular/core'; import { Subject } from 'rxjs/Subject'; @Injectable ...
- 【angular5项目积累总结】文件上传
<div class="form-group row"> <label class="col-sm-2 col-form-label"> ...
- 【angular5 项目积累总结】项目公共样式
main.css @font-face { font-family: 'wf_segoe-ui_normal'; src: local('Segoe UI'),url('../fonts/segoe- ...
- 【angular5项目积累总结】侧栏菜单 navmenu
View Code import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/co ...
- 【angular5项目积累总结】结合adal4实现http拦截器(token)
import { Injectable } from '@angular/core'; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRe ...
随机推荐
- WPF相关资料集锦
微软官方资料 .NET Framework源代码 https://referencesource.microsoft.com/ 微软官方文档 https://docs.microsoft.com/en ...
- 虚拟化安全 sandbox 技术分析
原文链接:https://cloud.tencent.com/developer/news/215218 前言: libvirt-4.3搭配qemu-2.12使用,如果使用默认的编译选项,可能会让qe ...
- Python----初次见面,请多关照!
1.计算机的最基本认识 CPU(大脑) 3GHZ + 内存(DDR4) + 主板 + 电源(心脏)+ 显示器 + 键盘 +鼠标+ 显卡 + 硬盘 80MB/s 操作系统分为: windows 家用 l ...
- Android性能测试-内存
前言: 近阶段都在探索android性能测试方面的东西,其中一个很重要的指标就是内存.对于内存,主要是一些gc是不是及时,或者说一些引用有没有及时释放,有没有导致oom或者内存持续增加导致卡顿,有没有 ...
- java 实验6 图形用户界面设计试验(2)
共两大题 窗体实现(略去测试类即 实例化自定义窗体) 小结: 1. JRadioButton 单选按钮 ButtonGroup 按钮集合(加入单选按钮) 清空选项需让ButtonGroup调用clea ...
- BZOJ 3110 [Zjoi2013]K大数查询 (CDQ分治+树状数组)
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...
- AngularJS源码解析4:Parse解析器的详解
$ParseProvider简介 此服务提供者也是angularjs中用的比较多的,下面我们来详细的说下这个provider. function $ParseProvider() { var cach ...
- 把redhat源换成centos的,解决redhat未注册不能下载相关软件的问题
修改 vim /etc/yum.repos.d/centos-base.repo如下,清华源地址为 https://mirrors.tuna.tsinghua.edu.cn/help/cento ...
- 在PL/SQL里直接插入日期时提示 is not a valid date and time的解决方法
在PL/SQL Developer里直接往表里插入日期格式的数据时,经常会出现" is not a valid date and time"的错误,这是因为Oracle的日期格式和 ...
- 机器学习笔记(四)--sklearn数据集
sklearn数据集 (一)机器学习的一般数据集会划分为两个部分 训练数据:用于训练,构建模型. 测试数据:在模型检验时使用,用于评估模型是否有效. 划分数据的API:sklearn.model_se ...