我需要在Angular2中构建一个readmore指令。这个指令将用于崩溃和扩展长文本块,并且#34;阅读更多"和"关闭"链接。不是基于字符数,而是基于指定的最大高度。
<div read-more [maxHeight]="250px" [innerHTML]="item.details">
</div>
任何人都可以指导在这种特定情况下获取/设置元素高度的最可靠方法。
关于如何实施这一特定指令的任何指导方针也将受到高度赞赏。
我需要构建像https://github.com/jedfoster/Readmore.js
这样的东西解决方案:
在Andzhik的帮助下,我能够构建符合我要求的以下组件。
import { Component, Input, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'read-more',
template: `
<div [innerHTML]="text" [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'">
</div>
<a *ngIf="isCollapsable" (click)="isCollapsed =! isCollapsed">Read {{isCollapsed? 'more':'less'}}</a>
`,
styles: [`
div.collapsed {
overflow: hidden;
}
`]
})
export class ReadMoreComponent implements AfterViewInit {
//the text that need to be put in the container
@Input() text: string;
//maximum height of the container
@Input() maxHeight: number = 100;
//set these to false to get the height of the expended container
public isCollapsed: boolean = false;
public isCollapsable: boolean = false;
constructor(private elementRef: ElementRef) {
}
ngAfterViewInit() {
let currentHeight = this.elementRef.nativeElement.getElementsByTagName('div')[0].offsetHeight;
//collapsable only if the contents make container exceed the max height
if (currentHeight > this.maxHeight) {
this.isCollapsed = true;
this.isCollapsable = true;
}
}
}
用法:
<read-more [text]="details" [maxHeight]="250"></read-more>
如果有任何改进,请随时提出建议。
答案 0 :(得分:21)
我制作了一个使用字符长度而不是div大小的版本。
import { Component, Input, ElementRef, OnChanges} from '@angular/core';
@Component({
selector: 'read-more',
template: `
<div [innerHTML]="currentText">
</div>
<a [class.hidden]="hideToggle" (click)="toggleView()">Read {{isCollapsed? 'more':'less'}}</a>
`
})
export class ReadMoreComponent implements OnChanges {
@Input() text: string;
@Input() maxLength: number = 100;
currentText: string;
hideToggle: boolean = true;
public isCollapsed: boolean = true;
constructor(private elementRef: ElementRef) {
}
toggleView() {
this.isCollapsed = !this.isCollapsed;
this.determineView();
}
determineView() {
if (!this.text || this.text.length <= this.maxLength) {
this.currentText = this.text;
this.isCollapsed = false;
this.hideToggle = true;
return;
}
this.hideToggle = false;
if (this.isCollapsed == true) {
this.currentText = this.text.substring(0, this.maxLength) + "...";
} else if(this.isCollapsed == false) {
this.currentText = this.text;
}
}
ngOnChanges() {
this.determineView();
}
}
用法:
<read-more [text]="text" [maxLength]="100"></read-more>
答案 1 :(得分:17)
我认为您需要Component
而不是Directive
。 Components
更有意义,因为您需要添加了解更多按钮/链接,即更新DOM。
@Component({
selector: 'read-more',
template: `
<div [class.collapsed]="isCollapsed">
<ng-content></ng-content>
<div (click)="isCollapsed = !isCollapsed">Read more</div>
</div>
`,
styles: [`
div.collapsed {
height: 250px;
}
`]
})
export class ReadMoreComponent {
isCollapsed = true;
}
用法:
<read-more>
<!-- you HTML goes here -->
</read-more>
答案 2 :(得分:15)
在Andzhik的帮助下,我能够构建符合我要求的以下组件。
import maya.cmds as cmds
#Put in your material names here. Make sure they have the EXACT SAME spelling, caps,
#and name conventions as in the Hypershade. And don't forget to put each one in ''!
matName = ['blue_mat','green_mat','red_mat','purple_mat']
cmds.shadingNode('surfaceShader',asShader=True,n='WhiteMat')
cmds.setAttr('WhiteMat.outColor', 1.0, 1.0, 1.0, type = 'double3')
cmds.shadingNode('surfaceShader',asShader=True,n='BlackMat')
cmds.setAttr('BlackMat.outColor', 0.0, 0.0, 0.0, type = 'double3')
for i in range(len(matName)):
cmds.select(cl=True)
cmds.select( ado=True)
cmds.createRenderLayer(n=matName[i]+'_layer')
cmds.hyperShade(objects=matName[i])
cmds.editRenderLayerGlobals(crl=matName[i]+'_layer')
for x in range(len(matName)):
if matName[x]!=matName[i]:
cmds.hyperShade(objects=matName[x])
cmds.hyperShade(assign='BlackMat')
else:
cmds.hyperShade(objects=matName[x])
cmds.hyperShade(assign='WhiteMat')
用法:
import { Component, Input, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'read-more',
template: `
<div [innerHTML]="text" [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'">
</div>
<a *ngIf="isCollapsable" (click)="isCollapsed =! isCollapsed">Read {{isCollapsed? 'more':'less'}}</a>
`,
styles: [`
div.collapsed {
overflow: hidden;
}
`]
})
export class ReadMoreComponent implements AfterViewInit {
//the text that need to be put in the container
@Input() text: string;
//maximum height of the container
@Input() maxHeight: number = 100;
//set these to false to get the height of the expended container
public isCollapsed: boolean = false;
public isCollapsable: boolean = false;
constructor(private elementRef: ElementRef) {
}
ngAfterViewInit() {
let currentHeight = this.elementRef.nativeElement.getElementsByTagName('div')[0].offsetHeight;
//collapsable only if the contents make container exceed the max height
if (currentHeight > this.maxHeight) {
this.isCollapsed = true;
this.isCollapsable = true;
}
}
}
答案 3 :(得分:1)
import { Component, Input,OnChanges} from '@angular/core';
@Component({
selector: 'read-more',
template: `
<div [innerHTML]="currentText"></div>
<span *ngIf="showToggleButton">
<a (click)="toggleView()">Read {{isCollapsed? 'more':'less'}}</a>
</span>`
})
export class ReadMoreDirective implements OnChanges {
@Input('text') text: string;
@Input('maxLength') maxLength: number = 100;
@Input('showToggleButton')showToggleButton:boolean;
currentText: string;
public isCollapsed: boolean = true;
constructor(
//private elementRef: ElementRef
) {
}
toggleView() {
this.isCollapsed = !this.isCollapsed;
this.determineView();
}
determineView() {
if (this.text.length <= this.maxLength) {
this.currentText = this.text;
this.isCollapsed = false;
return;
}
if (this.isCollapsed == true) {
this.currentText = this.text.substring(0, this.maxLength) + "...";
} else if(this.isCollapsed == false) {
this.currentText = this.text;
}
}
ngOnChanges() {
if(!this.validateSource(this.text)) {
//throw 'Source must be a string.';
console.error('Source must be a string.');
}
else{
this.determineView();
}
}
validateSource(s) {
if(typeof s !== 'string') {
return false;
} else {
return true;
}
}
}
和用法
<read-more [text]="this is test text" [maxLength]="10" [showToggleButton]="true"></read-more>
答案 4 :(得分:0)
如果要在不剪切任何单词的情况下将文本显示为最大字符数,请更改以下代码行:
this.currentText = this.text.substring(0, this.maxLength) + "...";
要:
this.currentText = this.text.substring(0, this.maxLength);
this.currentText = this.currentText.substr(0, Math.min(this.currentText.length, this.currentText.lastIndexOf(" ")))
this.currentText = this.currentText + "..."
答案 5 :(得分:0)
@Andrei Zhytkevich代码仅稍有改进 (对于降价很有用)
import {
Component,
AfterViewInit,
ViewChild,
ElementRef,
Attribute,
ChangeDetectionStrategy } from '@angular/core';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'ui-read-more',
template: `
<div [class.collapsed]="isCollapsed" [style.height]="_height">
<div #wrapper>
<ng-content></ng-content>
</div>
</div>
<div class="read-more">
<button
type="button"
class="btn btn-light" (click)="onIsCollapsed()">{{isCollapsed ? 'More' : 'Less'}}</button>
</div>
`,
styles: [`
:host{
display: block;
}
.collapsed {
overflow: hidden;
padding-bottom: 1rem;
}
.read-more{
display: flex;
justify-content: flex-end;
}
`]
})
export class UiReadMoreComponent implements AfterViewInit{
@ViewChild('wrapper') wrapper: ElementRef;
isCollapsed: boolean = true;
private contentHeight: string;
private _height: string;
constructor(@Attribute('height') public height: string = '') {
this._height = height;
}
ngAfterViewInit() {
this.contentHeight = this.wrapper.nativeElement.clientHeight + 'px';
}
onIsCollapsed(){
this.isCollapsed = !this.isCollapsed;
this._height = this.isCollapsed ? this.height : this.contentHeight;
}
}
<ui-read-more height="250px">
<ngx-md>
{{post.content}}
</ngx-md>
</ui-read-more>
答案 6 :(得分:0)
谢谢,由于控制台错误,我将其更改为NgOnInit。 略有变化,可以与Angular 6很好地配合。
@Component({
selector: 'app-read-more',
template: `
<div id="textCollapse" [innerHTML]="text" [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'">
</div>
<a *ngIf="isCollapsible" (click)="isCollapsed =! isCollapsed">Read {{isCollapsed ? 'more':'less'}}</a>
`,
styles: [`
div.collapsed {
overflow: hidden;
}
a {
color: #007bff !important;
cursor: pointer;
}
`]
})
export class ReadMoreComponent implements OnInit {
// the text that need to be put in the container
@Input() text: string;
// maximum height of the container
@Input() maxHeight: number;
// set these to false to get the height of the expended container
public isCollapsed = false;
public isCollapsible = false;
constructor(private elementRef: ElementRef) {
}
ngOnInit() {
const currentHeight = document.getElementById('textCollapse').offsetHeight;
if (currentHeight > this.maxHeight) {
this.isCollapsed = true;
this.isCollapsible = true;
}
}
}
如您所见,我更改了
const current Height = document.getElementById('textCollapse').offsetHeight;
答案 7 :(得分:0)
我又通过动态数据和完全控制解决了这类问题。
<div class="Basic-Info-para">
<p>
<span *ngIf="personalBasicModel.professionalSummary.length>200" id="dots">
{{personalBasicModel.professionalSummary | slice:0:200}} ...
</span>
<span id="more">{{personalBasicModel.professionalSummary }}
</span>
</p>
</div>
在此 personalBasicModel.professionalSummary 包含string。像任何文字一样。
slice:0:200 =将切片管道用于长度为200个字符的接合字符串。您可以根据需要更改长度。
id =“ dots”和id =“ more” 两件重要的事情。
<div class="Basic-Info-SeeMore">
<button class="SeeMore"(click)="showMore(paasValueOn_SeeMoreBtn)">
{{showLess_More}}
</button>
</div>
在这里,我们定义了一个带有动态文本(点击多看少)并带有点击事件的按钮。
// ---------------------------------- ts文件--------- -------------------------- //
定义变量
showLess_More :字符串=“查看更多...”;
paasValueOn_SeeMoreBtn :boolean = true;
用户单击“查看更多”按钮时会触发事件(方法)
showMore(data:boolean){
if(data){
$("#dots").css('display', 'none');
$("#more").css('display', 'inline');
this.showLess_More = "SEE LESS ...";
this.paasValueOn_SeeMoreBtn = false;
}else{
$("#dots").css('display', 'inline');
$("#more").css('display', 'none');
this.showLess_More = "SEE MORE...";
this.paasValueOn_SeeMoreBtn = true;
}
}
答案 8 :(得分:0)
您可以使用此插件。
仅通过传递要默认显示的[text]
和[textLength]
非常简单
https://www.npmjs.com/package/nga-read-more
答案 9 :(得分:0)
lineheight
很少的计算和一些CSS text-overflow: ellipsis;
可以完成这项工作。
.descLess {
margin-bottom: 10px;
text-overflow: ellipsis;
overflow: hidden;
word-wrap: break-word;
display: -webkit-box;
line-height: 1.8; <==== adjust line-height...a/q to your need
letter-spacing: normal;
white-space: normal;
max-height: 52px; <==== 250px etc:-
width: 100%;
/* autoprefixer: ignore next */
-webkit-line-clamp: 2; <==== clamp line 2...or 3 or 4 or 5...
-webkit-box-orient: vertical;
}
<div class="col-12 rmpm">
<div id="descLess" *ngIf="seeMoreDesc === 'false'" class="descLess col-12 rmpm">
{{inputData?.desc}}
</div>
<div *ngIf="seeMoreDesc === 'true'" class="col-12 rmpm" style="margin-bottom: 10px;line-height: 1.8;">
<!--Use Line height here-->
{{inputData?.desc}}
</div>
<span class="seeMore" *ngIf="seeMoreDesc === 'false' && lineHeightDesc > 21"
(click)="updateSeeMore('seeMoreDesc', 'true')">
See More
</span>
<span class="seeMore" *ngIf="seeMoreDesc === 'true'"
(click)="updateSeeMore('seeMoreDesc', 'false')">
See Less
</span>
</div>
declare const $:any;
seeMoreDesc = 'false';
seeMore = '';
inputData = {
'desc':'Lorem Ipusme dummy text..................'
}
constructor(
private eRef: ElementRef,
private cdRef : ChangeDetectorRef
) {}
ngAfterViewChecked() {
// pass line height here
this.lineHeightDesc = (Number($('#descLess').height()) / 1.8);
this.cdRef.detectChanges();
}
public updateSeeMore(type, action) {
if (type === 'seeMoreDesc') {
this.seeMoreDesc = action;
this.cdRef.detectChanges();
} else if (type === 'seeMore') {
this.seeMore = action;
this.cdRef.detectChanges();
}
}