[ionic3.x开发记录]参考ionic的float-label动效,写一个项目内通用的input组件,易扩展

上图:

module:

import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common"
import {PpInputComponent} from ‘./pp-input‘
import {FormsModule} from "@angular/forms";

@NgModule({
  declarations: [PpInputComponent],
  imports: [
    CommonModule,
    FormsModule,
  ],
  exports: [PpInputComponent],
})

export class PpInputComponentModule {
}

 ts:

import {Component, Input, Output, EventEmitter, OnInit, ViewChild, ElementRef, Renderer2, AfterViewInit} from ‘@angular/core‘;

/**
 * Generated class for the PpInputComponent component.
 *
 * See https://angular.io/api/core/Component for more info on Angular
 * Components.
 */
@Component({
  selector: ‘pp-input‘,
  templateUrl: ‘pp-input.html‘
})
export class PpInputComponent implements OnInit, AfterViewInit {
  constructor(private renderer: Renderer2) {
  }

  @ViewChild(‘ppLabel‘) private ppLabel: ElementRef; // 获取元素
  @Input() ppValue: any; // input的值,双向绑定
  @Input(‘pp-label‘) label: string = ‘Label‘; // label文案
  @Input() validate: any = function (input) { // 验证数据方法
    if (input) {
      return true
    } else {
      return false
    }
  };
  @Input() type: string = ‘text‘; // input类型
  @Input() x: string; // label的X轴偏移量
  @Input() isRequired: boolean; // false
  @Input(‘error-message‘)  errorMessage: string = ‘validate error‘; // 错误提示信息

  @Output() ppValueChange = new EventEmitter();

  actived: boolean = false; // 样式控制
  float: boolean; // label是否浮动
  showErrMsg: boolean = false; // 是否显示错误信息

  ngOnInit() {
    if (this.ppValue) {
      this.float = true;
      this.actived = true;
    } else {
      this.float = false;
    }
  }

  ngAfterViewInit() {
    if (this.x) {
      this.renderer.setStyle(this.ppLabel.nativeElement, ‘transform‘, `translate3d(${Number(this.x) / 100}rem, 0.48rem, 0)`)
    }
  }

  // 获得焦点
  ppFocus() {
    this.float = true;
  }

  // 失去焦点
  ppBlur() {
    if (this.ppValue) {
      this.float = true;
    } else {
      this.float = false;
    }
    if (this.validate(this.ppValue)) {
      this.showErrMsg = false;
    } else {
      this.showErrMsg = true;
    }
  }

  // 更新父组件model值
  changeValue() {
    this.ppValueChange.emit(this.ppValue);
    if (this.validate(this.ppValue)) {
      this.actived = true;
      this.showErrMsg = false;
    } else {
      this.actived = false;
    }
  }
}

  scss

pp-input {
  .pp-input-container {
    border-bottom: 1px solid #C1CCD5;
    height: 0.92rem;
    &.actived {
      border-color: #6308C7
    }
    .label {
      font-size: 0.28rem;
      color: #95A1AB;
      position: relative;
      font-family: Avenir-Medium;
      pointer-events: none;
      transform: translate3d(0,0.48rem, 0);
      transition: all 0.2s;
      margin: 0.11rem 0.08rem 0.11rem 0;
      &.actived {
        transform: translate3d(0, 0, 0)!important;
        font-size: 0.22rem;
        transition: all 0.2s;
        .actived {
          color: #6308C7
        }
      }
      .required {
        color: #F44E4E
      }
    }
    .pp-input {
      border: none;
      font-size: 0.28rem;
      height: 0.5rem;
      line-height: 0.5rem;
    }
    .content {
      display: flex;
      align-items: center;
    }
  }
  .error-message {
    color: #F44E4E;
    font-size: 0.22rem;
    height: 0;
    line-height: 0.4rem;
    opacity: 0.5;
    transition: all 0.2s;
    overflow: hidden;
    &.show {
      opacity: 1;
      height: 0.4rem;
      transition: all 0.2s;
    }
  }
}

  html

<!-- Generated template for the PpInputComponent component -->
<div class="pp-input-wrapper">
  <div class="pp-input-container" [class.actived]="actived">
    <div class="label" [class.actived]="float" #ppLabel>
      <span class="required" *ngIf="isRequired">*</span><span [class.actived]="actived">{{label}}</span>
    </div>
    <div class="content">
      <ng-content></ng-content>
      <input class="pp-input"
             (focus)="ppFocus()"
             (blur)="ppBlur()"
             (keyup)="changeValue()"
             [type]="type"
             [(ngModel)]="ppValue">
    </div>
  </div>
  <div class="error-message" [class.show]="showErrMsg">{{errorMessage}}</div>
</div>

 目前实现可传入label文案, label的x轴偏移,input类型,验证数据的validate方法,input的双向绑定value值,错误提示信息等

用<ng-content></ng-content>预留的编辑位置,可以添加更多的html,方便扩展,例如上图的国家图标显示。

可以考虑把所有的@Input集合成一个config,html的font-size的值我是动态算的,所以样式rem的值可能要修改成你需要的大小。

ps: 之前用vue组件也写过类型的组件,传送门:https://www.cnblogs.com/cong-bao/p/9204940.html

原文地址:https://www.cnblogs.com/cong-bao/p/9448029.html

时间: 2024-11-05 13:51:44

[ionic3.x开发记录]参考ionic的float-label动效,写一个项目内通用的input组件,易扩展的相关文章

[ionic3.x开发记录]ng-content使用

在ionic开发公用组件的时候,我一直在想有没有angular有没有像vue一样的slot插槽.方便组件后期扩展. 然后去翻文档,发现有ng-content这么个东西,用法很像vue的slot. 组件预留插槽位置 <div class="header-wrapper"> <div class="header"> <span class="back" *ngIf="showBackButton"&g

个人知识管理系统Version1.0开发记录(03)

demo  设 计 一个知识点demo,在数据库和用户界面的互动事件.分三个层次,数据存储,数据方法工具,数据呈现界面.这一次先完成数据存储,按以下逻辑实现.工具:eclipse,oracle数据库,sqldeveloper(改用oracle的sqldeveloper).(当后面数据库复杂时可以考虑PowerDesigner.) 1.考虑软件功能.数据方法.商业元素.逻辑扩展等实用因素,设计实体类. 2.用jdbc连接oracle数据库. 3.数据储存在数据库中,分析oracle数据库的数据类型

ionic3+angular4开发混合app 之自定义组件

这里主要是记录ionic3+angular4开发混合app时自定义组件,我想自定义组件的方法和angular4应该类似,具体在纯angular4中自定义组件,暂时没有实践,个人觉得差别不大,之后实践了会再次更新. 首先,在ionic3中有命令可以直接创建一个组件:ionic g component componentName 使用这个命令创建的组件会在components目录下生成一个组件文件夹和一个module文件,具体目录,请看截图:我这里是有3个小组件 并且会把你创建的组件自动import

CozyRSS开发记录5-订阅列表栏里的项

CozyRSS开发记录5-订阅列表栏里的项 1.订阅列表栏里的项的原型图 这里列表项依然参考傲游的RSS阅读器,以后可能会微调. 2.使用ControlTemplate来定制ListBoxItem 给展示RSS源名称的TextBlock设置MaxWidth和ToolTip,是为了优化名称过长的情况. 这里暂时把内容都写死,后面会使用MVVM和bindling来处理. 3.ListBox效果展示 最后,我们修改ListBox的xaml,用上我们的模版. 效果还行

个人知识管理系统Version1.0开发记录(08)

切入点 前面,我们已经搭建好了web端的一种基本结构,需要进一步定位的主要问题有三点: 1.界面的选择和确定,用extjs做的初步样式,进一步改动为jqueryUI/html,再进一步改变为HTML5等.我们思考一种用户思维,只要有一个地方让用户不喜欢,用户就会全盘否定该款软件:所以,软件界面一定要简单.精致.能引起用户的兴趣.符合用户习惯和用户思维. 2.框架的选择和确定,struts2,hibernate/mybatis,spring等,在编写知识体核心功能模块前,需要完成选择和改写. 3.

个人知识管理系统Version1.0开发记录(04)

demo model 我们采用mvc软件架构模式,方便以后用Struts2框架技术优化.重构.封装.这次主要设计一些常用的方法工具,即数据访问逻辑.工具:eclipse.oracle.sqldeveloper. 思路如下: 1.  用sqldeveloper新建表oneds,写入一条name="cookie"的数据. 细节: 参数越多,越要细致检查单词拼写. 2.  用java读取和写入对象属性,与数据库互动. 3.  用java进行数据访问,先完成五个方法,查询所有知识点,增加知识点

CozyRSS开发记录1-原型图与Grid

CozyRSS开发记录1-原型图与Grid 1.使用MockPlus画出最简陋的原型图 这个界面参考了目前我最常使用的RSS阅读-傲游浏览器的内置RSS阅读器.主体框架划分为上.左下.右下三块,分别是标题栏(工具类)TitleBar.订阅列表栏RSSListFrame.订阅内容栏RSSContentFrame.订阅内容栏又划分为上.左下.右下三部分,分别是RSSContentTitle.RSSContentList.RssContentView. 2.建立CozyRSS工程,用Grid划分窗口

CozyRSS开发记录17-Html2Xaml

CozyRSS开发记录17-Html2Xaml 1.RssContentView还需要优化 上回做了RssContentView的显示,但是对于rss返回的描述(摘要),连换行的没有,更别说里面还有html描述符了.换行比较好解决,加个限定大小,再加一个自动换行的描述就可以了: TextWrapping="Wrap"  Margin="10 12 10 10" 2.在wpf里显示html的方法 显示html,有两个方向: A.直接显示html B.将html转换成别

个人知识管理系统Version1.0开发记录(11)

关 键 字 搜 索 (1)匹配单个属性的关键字:(2)匹配单个对象的关键字:(3)匹配对象集合的关键字:(4)基于事件驱动的:(5)实时搜索,参考win7的搜索功能. 1.备份,java代码,数据库数据. 2.oracle数据库,用户操作. (1)查看数据库默认表空间. select * from database_properties;(2)创建用户create user 用户名 identified by 密码 默认表空间 临时表空间create user dyl identified by