I'm trying to validate dynamically generated inputs, but I do not know how to do this.
When I add the div that triggers the directive and inserts the inputs dynamically the div adds the 'has-error' class but does not apply the input style, anyone knows the best way to do this that I'm trying to do?
Here is the markup:
<div ng-if="conditionItem.field.id"
ng-class="{true: 'has-error'}[conditionItem.field.hasError]"
dynamic
input-router
source="conditionItem.field"
ng-click="FieldConditionsCtrl.valueTest(conditionItem.field.hasError)"
ng-required="true"
ng-model="conditionItem.situation[$index]">
</div>
Here is the directive how generate the inputs:
(function() {
'use strict';
angular
.module('applicationInputs', ['rzModule', 'focus-if', 'ui.utils.masks'])
.directive('inputRouter', inputRouter);
/** #ngInject */
function inputRouter($compile){
return {
restrict: 'EA',
scope: {
ngModel: '=',
source: '=',
placeholder: '#',
tabIndex: '='
},
link: function(scope, element, attrs) {
var canvas = angular.element(element[0]);
scope.source.editable = angular.isUndefined(scope.source.editable) ? true : scope.source.editable === true;
//used by setting to override selected field
if (angular.isDefined(attrs.dynamic)) {
scope.$watch('source', function () {
var html = '<' + scope.source.type + 'input></' + scope.source.type + 'input>';
canvas.children().detach();
canvas.append($compile(html)(scope));
});
} else {
var html = '<' + scope.source.type + 'input></' + scope.source.type + 'input>';
canvas.append($compile(html)(scope));
}
}
}
}
})();
Here is my style:
.has-error {
border-color: red
}
Try border: 1px solid red; instead of just setting border-color. Border width is 0 by default, so just setting a color isn't enough
Just a couple nitpicky-subjective style comments also:
element is already a jqLite/jquery element, so no need to call angular.element
the scope.source.editable === true assignment can be shortened to !!scope.source.editable if you really want it to be a boolean.
While clever, this sort of jquery style element building is generally a code smell in angular js. If you really want to go this route, I would build self-contained directives for your inputs and use inputRouter's template to choose. It's easier to understand, so your future self will thank you
{true: 'has-error'}[conditionItem.field.hasError] took me a minute. Just write it as {conditionItem.field.hasError: 'has-error'}
I'm a big fan of these style guides for AngularJS:
John Papa - ES5, but good advice
Todd Motto - ES6+
There's overlap, but take what you like from each.
Hey everyone I am currently building a mobile app for my company and I have a angularjs function that is currently adding a css class based on whether it's day or night. It does what it's supposed to do perfectly by putting a day or night image based on whether it's day or night.
The issue I am running into is that when testing the app right before the clock let's say goes from 1:59 to 2 it doesn't change the background image until you refresh the page. I want it to automatically change the background image without having to refresh and can't seem to find a way to do it. I will link the code here!
Any help is appreciated as it has me completely stumped...
Here is what I have in my html.
<div class="dashboard-welcome" ng-class="{'hide-homescreen-image-landscape'
: isLandscape, 'homescreenImageDay' : isDay, 'homescreenImageNight' :
isNight }">
Here is where the function is being called
angular.module('starter').controller('homeCtrl', ['$scope', '$interval',
'jsBridge', 'authService', 'tierService', '$window', fnc]);
function fnc($scope, $interval, jsBridge, authService, tierService, $window)
{
$scope.$on('$ionicView.afterEnter', function (event, viewData) {
setOrientation();
$scope.isDay = !isDayTime(1000);
$scope.isNight = isDayTime(1000);
});
Here is where the function is instantiated. Basically checking what time it is.
var isDayTime = function () {
var h = new Date().getHours();
if (h >= 14) {
return true;
} else {
return false;
}
}
I can't supply all the code since this application is thousands of lines long but this is the working function as of now. Just need it to switch background images without refreshing using angularjs...
Assuming that inside your div you are using an background-image: url("...")
I suggest you set up an object to hold a single $scope.isDay value instead of doing the calculation twice.
Also use the $interval service to check every nth millisecond to update your $scope.isDay value.
The code below works fine in dynamically changing a background image on a page using its CSS class.
HTML:
<div ng-class="data.isDay ? 'back1' : 'back2'"></div>
JS:
var exampleApp = angular.module('exampleApp', []);
exampleApp.controller('exampleController', function($scope, $interval) {
$scope.data = {
isDay: true,
classVal: {
one: 'text-danger',
two: 'text-success'
}
};
$interval(function() {
$scope.toggleImage();
}, 600);
$scope.toggleImage = function() {
$scope.data.isDay = ($scope.data.isDay ? false : true)
};
$scope.toggleImage();
});
Here is also a plnkr demo
I'm making an angular directive that hides element a when the user scrolls on element b. It works fine, but I can't figure out this behaviour:
It might be hard to tell, but essentially when you scroll to the bottom the scroll bar expands because element a sits above element b, so essentially the thing I'm scrolling on has more space available. After that, I'm not sure why it scrolls up. Here's a gif of the full page if that makes it any clearer:
My directive is written in typescript (angular version 1.5.7 NOT 2.x), I'll work on translating it to javascript but in the interest of getting this question out there as quickly as possible here's the ts:
interface IScope extends ng.IScope {
showHeader: boolean;
}
export class IncodeHideHeaderDirective implements ng.IDirective {
restrict = "AE";
require: "ngModel";
scope: Object;
replace = true;
link: ng.IDirectiveLinkFn | ng.IDirectivePrePost;
oldy: number;
justScrolled = false;
constructor() {
const self = this;
this.link = (scope: IScope, element: ng.IAugmentedJQuery) =>
{
element.bind("scroll",
() => {
if (element[0].scrollTop > self.oldy) {
console.log("collapsing");
scope.$eval("showHeader=false");
}
else if (element[0].scrollTop < self.oldy)
{
console.log("expanding");
scope.$eval("showHeader=true");
}
self.oldy = element[0].scrollTop;
}
);
element.bind("load",
() => {
console.log(scope);
this.oldy = element[0].scrollTop;
});
};
}
public static factory(): ng.IDirectiveFactory {
const directive = () => new IncodeHideHeaderDirective();
return directive;
}
}
angular.module("incode.module")
.directive("ixHeader", incode.directives.label.IncodeHideHeaderDirective.factory());
pretty basic stuff. How do I get the scrollbar to stop doing this weird stuff?
Here's a fiddle demonstrating the problem.
That's not an Angular answer, but why not just remove your header bar from the flow by making it position: fixed (or absolute) ? It would not cause the reflow of the main contents, and you would have none of the issues you are experiencing.
.slideUp {
/* ... */
position: fixed;
}
https://jsfiddle.net/e8j938g8/3/
I am using dotdotdot seems to bea cool plug-in... however, I need to use it an angular, is not working if new elements are loaded (via http.get <> ng-repeat)...
So I find that there is an angular-dotdotdot... How to use it? is not very clear...
Suppose I have the classical usage of dotdotdot like this:
// ellipsis body to 4 lines height
var ellipsis = $(".ellipsis-case-body");
var nrLines = 4;
var ellHeight = parseInt(ellipsis.css('line-height'), 10) * nrLines;
ellipsis.dotdotdot({ height: ellHeight });
// ellipsis title to 1 line height
ellipsis = $(".ellipsis-case-title");
nrLines = 1;
ellHeight = parseInt(ellipsis.css('line-height'), 10) * nrLines;
ellipsis.dotdotdot({ height: ellHeight });
How to use it with angular?
In their documentation
$scope.myText = 'some really long text';
Template:
<p dotdotdot='myText'>{{myText}}</p>
But how to set options?
It doesn't look like you can. This is the directive source code, from GitHub:
angular.module('dotdotdot-angular', [])
.directive('dotdotdot', ['$timeout', function($timeout) {
return {
restrict: 'A',
link: function(scope, element, attributes) {
// We must pass in the scope binding, e.g. dotdotdot='myText' for scope.myText
scope.$watch(attributes.dotdotdot, function() {
// Wait for DOM to render
// NB. Don't use { watch: true } option in dotdotdot as it needlessly polls
$timeout(function() {
element.dotdotdot();
}, 400);
});
}
}
}]);
Note that there is nothing being passed to .dotdotdot().
You will probably want to fork this or just write your own.
I'm writing a component using AngularJS and AngularJS directives.
I'm doing something like this:
var MyApp = angular.module('MyApp', []);
MyApp.directive('myTag', function() {
return { /* Some logic here*/ }
});
I want to be able to change style of my component (using CSS), something like this:
<my-tag class="MyClass"></my-tag>
Besides this I want to be able to manipulate all elements style inside my
component (HTML markup inside of my-tag).
Do you have any advice or useful examples how to manipulate the style properties of custom tags using AngularJS?
This should do the trick.
var MyApp = angular.module('MyApp', []);
MyApp.directive('myTag', function() {
return {
link: function(scope, element, attributes){
element.addClass('MyClass');
}
}
});
This is how AngularJS adds core CSS styles:
angular.element(document).find('head').prepend('<style type="text/css">#charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}</style>');
You can find this code in angular.js v1.2.0-rc.2.
EDIT
In a custom directive, I use this solution to bundle CSS stylesheets in the directive:
var outputColorCSS = {
selector: 'span.ouput-color',
rules: [
'display: inline-block',
'height: 1em',
'width: 5em',
'background: transparent',
'border: 3px solid black',
'text-align: center',
'font-weight: bold',
'font-size: 0.8em'
]
};
var outputColorStyleSheet = outputColorCSS.selector + outputColorCSS.rules.join(';');
angular.element(document).find('head').prepend('<style type="text/css">' + outputColorStyleSheet + '</style>');
Then you can use class="ouput-color" in your directive templates.
I found it very clean and useful.
I'm a little late to the party, but why aren't you all using the built in .css() method?
just use:
link: function(scope, elem, attr, ctrl)
{
elem.css({'display': 'block', 'height': '100%', 'width': '100%'});
}
or whatever css you desire.
You can put custom styles in a directive's declaration with a parameter, just like you exemplified.
In order to declare a style like that, you have to define a variable to hold the custom styles:
scope: {
myClass: '#myClass'
},
And then set that parameter in the directive's template, like this:
<my-tag my-class="CustomClass"></my-tag>
Finally, in the template of the directive itself, reference that class:
<h1 class="{{myClass}}">{{myContent}}</h1>
I made a plunker that shows how you can customize styles in a directive, check it out here .
Plunker
To manipulate the css style through an attribute directive, you could do something like this:
var app = angular.module('colorSwap', []);
app.directive('styleChanger', function() {
return {
'scope': false,
'link': function(scope, element, attrs) {
var someFunc = function(data)
{
/* does some logic */
return 'background-color:' + data;
}
var newStyle = attrs.styleChanger;
scope.$watch(newStyle, function (style) {
if (!style) {
return ;
}
attrs.$set('style', someFunc(style));
});
}
};
});
Some html:
<div ng-app="colorSwap">
<input type="txt" ng-init="colorName= 'yellow'" ng-model="colorName" />
<div style-changer="colorName">this is the div content</div>
</div>
To make an element directive, change it's own style, something like this:
app.directive('elementWithStyle', function() {
return {
'restrict' : 'E',
'scope': {},
'controller': function($scope) {
$scope.someStyle = 'Cyan';
$scope.someFunc = function() { $scope.someStyle = 'purple' };
},
'template': '<div style="background: {{someStyle}}" ng-click="someFunc()"> click me to change colors </div>'
}
});
And the html:
<div ng-app="colorSwap">
<element-with-style>123</element-with-style>
</div>
I hope this helps. The rest of the answers cover class manipulation more or less.
For css manipulation inside of the childs of your directive try this:
var MyApp = angular.module('MyApp', []);
MyApp.directive('myTag', function() {
return {
link: function(scope, element, attr){
// For your tag
element.addClass('MyClass');
// For elements inside your directive tag
var tag_childs = element[0].childNodes;
for(var i = 0; i < element[0].childElementCount; i++){
tag_childs[i].style.height = '70px';
}
}
}
});
Here is an example, please note that this is probably not the best use of AngularJS, being declarative, you would likely want to just put the classes on the markup. However, just so you understand what's going on, let me demonstrate a simple directive to do what you first asked.
var MyApp = angular.module('MyApp', []);
MyApp.directive('myTag', function($compile) {
return {
restrict: 'E', // this means it will be an element
link: function(scope, element, attrs, ctrl) {
// First, I included the $compile service because it will be needed
// to compile any markup you want to return to the element.
// 1. Add the class, as you wanted
element.addClass('MyClass');
// 2. Add markup
var html = '<div>Hello World</div>';
//Compile it and add it back
$compile(html)(scope);
element.html(html);
}
};
});
Finally, on your markup, you just put this in:
<my-tag />
app.directive('bookslist', function() {
return {
scope: true,
templateUrl: 'templates/bookslist.html',
restrict: "E",
controller: function($scope){
},
link: function(scope, element, attributes){
element.addClass('customClass');
}
}
});
.customClass table{
background: tan;
}
.customClass td{
border: 1px solid #ddd;
}
<!DOCTYPE html>
<html>
<head>
<link href="app.css" rel="stylesheet">
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
<title>Task</title>
</head>
<body ng-app="app">
<div ng-controller="myCtrl">
<bookslist></bookslist>
</div>
</body>
</html>
Angular
app.directive("time",function(){
var directive={};
directive.restrict="A";
directive.link=function(scope,element,attr,ctrl){
element.css({
backgroundColor:'#ead333'
});
}
var time=new Date().toTimeString();
directive.template=time;
return directive;
});
HTML
The times is <span time></span>
I didn't found the perfect solution just yet, but I'm following John Papa's styling of controllers even with directives:
the directive is a folder (directiveName.directive)
3 files inside: directiveName.directive.js, directiveName.template.html, directiveName.styles.css
use templateUrl when declaring the directive. The template has the link to the css file, as usual
I found it to be very clean and follows a pattern. The bad side of it is that you create several <link> tags near the directives in the rendered HTML (not seem to be a issue still, though). Check out this comment too.
That being said, take a look at Angular 1.5 component's. It's relatively new and has a much better approach. Now I use directives only for DOM manipulation (not reusability as components).