如何在 Angular 中实现带有省略号和标签的(动态宽度)文本输入?
How to implement a (dynamic-width) text input with ellipsis and label in Angular?
如果用户提供的值太长而无法在UI.
文本输入将是动态宽度的,旁边有一个文本标签,并且输入应该在标签后使用所有可用的 space。
无论长度如何,标签都应该是一行。
但是,我知道 HTML 文本输入 (<input>
) 不能有省略号 ,只有常规 HTML 元素,例如 <div>
可以。
这能以某种方式实现吗?
有很多事情在起作用:
- 该值显示为常规
<span>
(以便能够显示省略号),单击时,显示 <input>
(由 editing
变量控制)
focusMe
指令用于在创建 <input>
以替换 <span>
时将焦点放在 <input>
上
nonBreaking
过滤使文本标签显示在一行
- 基于flexbox的各种CSS规则控制显示
overflow
, text-overflow
注意省略号
white-space: nowrap
和 flex-shrink: 0
确保文本标签没有分成多行
flex-grow: 1
确保 <input>
占用所有额外的 space 可用
缺点:
- 当用户第一次点击静态
<span>
时,光标放在 <input>
的开头,而不是用户点击的地方(如果他点击中间)
- 当标签长于视口宽度时,将不会显示文本输入(假设视口宽度总是比标签长度宽得多)
附加信息:
添加验证时,如果模型处于无效状态,您可能希望保持 <input>
显示,否则绑定值为空,跨度将为空。
要做到:
- 将 "name" 传递给指令并在内部执行
<input name="{{name}}">
- 改为
<span ng-show="!editing && form.{{name}}.$valid">
- 改为
<input ng-show="editing || !form.{{name}}.$valid">
完整代码:
HTML:
<!doctype html>
<html ng-app="plunker">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<script src="script.js"></script>
<link rel="stylesheet" href="style.css">
<script type="text/ng-template" id="InputTextWithEllipsis.html">
<div class="input-text-with-ellipsis-wrapper">
<label class="mylabel" ng-bind-html="mylabel | nonBreaking"></label>
<span class="dual-input-wrapper">
<span
ng-show="!editing"
ng-click="editing = true"
class="static-text-with-ellipsis">{{mymodel}}</span>
<input
ng-show="editing"
ng-focus="editing = true"
ng-blur="editing = false"
focus-me="editing"
ng-model="mymodel"
class="editable-textinput" />
</span>
</div>
</script>
</head>
<body ng-controller="MainCtrl">
<form name="profile">
<input-text-with-ellipsis
mylabel="'Name'"
mymodel="dataModel.name"
></input-text-with-ellipsis>
<input-text-with-ellipsis
mylabel="'Last Name'"
mymodel="dataModel.lastName"
></input-text-with-ellipsis>
<input-text-with-ellipsis
mylabel="'A very long label here'"
mymodel="dataModel.lastName"
></input-text-with-ellipsis>
</form>
</body>
</html>
JS:
var myModule = angular.module('plunker', []);
myModule.filter('nonBreaking', function($sce) {
return function(inputStr) {
var outputStr = inputStr.replace(/\s/g, ' ');
return $sce.trustAsHtml(outputStr);
};
});
/*
*
*/
myModule.directive('focusMe', function($timeout, $parse) {
return {
link: function(scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function(value) {
if (value === true) {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
myModule.controller('MainCtrl', function($scope) {
$scope.dataModel = {
name: "Fernando",
lastName: "Fernandez Sanchez de la Frontera"
}
});
myModule.directive('inputTextWithEllipsis', function(){
return {
restrict: 'E',
templateUrl: 'InputTextWithEllipsis.html',
require: ['^form'],
scope: {
mylabel: '=',
mymodel: '='
},
link: function(scope, element, attrs, ctrls) {
scope.editing = false;
}
};
});
CSS:
* {
font: 16pt sans-serif;
border: 0;
padding: 0;
margin: 0;
outline: 0;
}
.input-text-with-ellipsis-wrapper {
background-color: linen;
padding: 10px;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
}
.mylabel {
background-color: #ffddcc;
margin-right: 10px;
flex-basis: auto;
flex-shrink: 0;
min-width: 50px;
}
.dual-input-wrapper {
flex-basis: auto;
flex-grow: 1;
overflow: hidden;
white-space: nowrap;
text-align: right;
}
.editable-textinput {
background-color: #ddf;
width: 100%;
text-align: right;
}
.static-text-with-ellipsis {
background-color: #eeccbb;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
如果用户提供的值太长而无法在UI.
文本输入将是动态宽度的,旁边有一个文本标签,并且输入应该在标签后使用所有可用的 space。
无论长度如何,标签都应该是一行。
但是,我知道 HTML 文本输入 (<input>
) 不能有省略号 ,只有常规 HTML 元素,例如 <div>
可以。
这能以某种方式实现吗?
有很多事情在起作用:
- 该值显示为常规
<span>
(以便能够显示省略号),单击时,显示<input>
(由editing
变量控制) focusMe
指令用于在创建<input>
以替换<span>
时将焦点放在 nonBreaking
过滤使文本标签显示在一行- 基于flexbox的各种CSS规则控制显示
overflow
,text-overflow
注意省略号white-space: nowrap
和flex-shrink: 0
确保文本标签没有分成多行flex-grow: 1
确保<input>
占用所有额外的 space 可用
<input>
上
缺点:
- 当用户第一次点击静态
<span>
时,光标放在<input>
的开头,而不是用户点击的地方(如果他点击中间) - 当标签长于视口宽度时,将不会显示文本输入(假设视口宽度总是比标签长度宽得多)
附加信息:
添加验证时,如果模型处于无效状态,您可能希望保持 <input>
显示,否则绑定值为空,跨度将为空。
要做到:
- 将 "name" 传递给指令并在内部执行
<input name="{{name}}">
- 改为
<span ng-show="!editing && form.{{name}}.$valid">
- 改为
<input ng-show="editing || !form.{{name}}.$valid">
完整代码:
HTML:
<!doctype html>
<html ng-app="plunker">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<script src="script.js"></script>
<link rel="stylesheet" href="style.css">
<script type="text/ng-template" id="InputTextWithEllipsis.html">
<div class="input-text-with-ellipsis-wrapper">
<label class="mylabel" ng-bind-html="mylabel | nonBreaking"></label>
<span class="dual-input-wrapper">
<span
ng-show="!editing"
ng-click="editing = true"
class="static-text-with-ellipsis">{{mymodel}}</span>
<input
ng-show="editing"
ng-focus="editing = true"
ng-blur="editing = false"
focus-me="editing"
ng-model="mymodel"
class="editable-textinput" />
</span>
</div>
</script>
</head>
<body ng-controller="MainCtrl">
<form name="profile">
<input-text-with-ellipsis
mylabel="'Name'"
mymodel="dataModel.name"
></input-text-with-ellipsis>
<input-text-with-ellipsis
mylabel="'Last Name'"
mymodel="dataModel.lastName"
></input-text-with-ellipsis>
<input-text-with-ellipsis
mylabel="'A very long label here'"
mymodel="dataModel.lastName"
></input-text-with-ellipsis>
</form>
</body>
</html>
JS:
var myModule = angular.module('plunker', []);
myModule.filter('nonBreaking', function($sce) {
return function(inputStr) {
var outputStr = inputStr.replace(/\s/g, ' ');
return $sce.trustAsHtml(outputStr);
};
});
/*
*
*/
myModule.directive('focusMe', function($timeout, $parse) {
return {
link: function(scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function(value) {
if (value === true) {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
myModule.controller('MainCtrl', function($scope) {
$scope.dataModel = {
name: "Fernando",
lastName: "Fernandez Sanchez de la Frontera"
}
});
myModule.directive('inputTextWithEllipsis', function(){
return {
restrict: 'E',
templateUrl: 'InputTextWithEllipsis.html',
require: ['^form'],
scope: {
mylabel: '=',
mymodel: '='
},
link: function(scope, element, attrs, ctrls) {
scope.editing = false;
}
};
});
CSS:
* {
font: 16pt sans-serif;
border: 0;
padding: 0;
margin: 0;
outline: 0;
}
.input-text-with-ellipsis-wrapper {
background-color: linen;
padding: 10px;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
}
.mylabel {
background-color: #ffddcc;
margin-right: 10px;
flex-basis: auto;
flex-shrink: 0;
min-width: 50px;
}
.dual-input-wrapper {
flex-basis: auto;
flex-grow: 1;
overflow: hidden;
white-space: nowrap;
text-align: right;
}
.editable-textinput {
background-color: #ddf;
width: 100%;
text-align: right;
}
.static-text-with-ellipsis {
background-color: #eeccbb;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}