Angular- Creating a directive from existing html content/ - angularjs

Assume
You have html that you can not modify the inner contents of- but you CAN modify the element attributes.
Your goal is to perform 3d transformations on the element that are bidirectionally linked to the value of 3 range inputs.
One input for X rotation, Y Rotation and Z Rotation.
In order to do that, I think I need to use a directive-- but if I use a directive it will erase the existing html...
see this codepen for the current version.
HTML
<html ng-app="truck">
<head></head>
<body>
<section ng-controller="TruckCtl">
<section class="controls">
<fieldset>
<legend>Rotation</legend>
<div>
<label for="xRotation">X:</label>
<input id="xRotation" ng-model="Rotation.x" type="range" min="0" max="360">
<span ng-bind="Rotation.x"></span>
</div>
<div>
<label for="yRotation">Y:</label>
<input name="yRotation" ng-model="Rotation.y" type="range" min="0" max="360">
<span ng-bind="Rotation.y"></span>
</div>
<div>
<label for="zRotation">Z:</label>
<input name="zRotation" ng-model="Rotation.z" type="range" min="0" max="360">
<span ng-bind="Rotation.z"></span>
</div>
</fieldset>
</section>
<section class="wrapper">
<div id="truck" ng-model="Rotation">
</div>
</section>
</section>
</body>
</html>
JS
(function(){
"use strict";
var app = angular.module('truck', []);
app.controller("TruckCtl", function($scope){
$scope.Rotation = {
x: 0,
y: 0,
z: 0
};
});
//no dice v
app.filter("rotate", function() {
return function(input) {
return model.style({
"-webkit-transform" : "rotateX(" + Rotation.x + "deg)"
});
console.log(model);
}
});
//Directives are where I ge lost.
app.directive("Rotation", function(){
return function(scope, element, attrs){
//what do?
}
});
})();
also:
I have no idea why this fiddle doesn't work.

I would recommend to get it working by keeping things simple first. Once you have code that works, you can refactor it out into a filter and directive. The angular docs cover how to implement a directive pretty well, you can basically just copy, paste, and modify. If you have specific questions I'm sure you'll find answers here or elsewhere. As far as simple code to achieve your goal; your controller along with this HTML will rotate as specified:
<div id="truck" style="-webkit-transform: rotateX({{Rotation.x}}deg) rotateY({{Rotation.y}}deg) rotateZ({{Rotation.z}}deg);"></div>
Also, BTW - js convention is to use camelCasing. $scope.Rotation should be $scope.rotation (lowercase r). Use PascalCase for constructors. Although it is purely a preference, you'll find most libraries adhere to this convention.

So the TLDR version is that my nesting was off so my scopes were wrong.
Also I should've been using a factory rather than a filter or a directive.
Working example can be found: here
--one caveat is that it doesn't work until you adjust all the values first.
so just move all of the range sliders to 0 and then change them as you please
html
<section ng-app="truck">
<section id="wrapper" ng-controller="Truck">
<section class="controls">
<fieldset>
<legend>Rotation</legend>
<div>
<label for="xRotation">X:</label>
<input id="xRotation" ng-model="Rotation.x" type="range" min="-100" max="100">
[[Rotation.x]]
</div>
<div>
<label for="yRotation">Y:</label>
<input id="yRotation" ng-model="Rotation.y" type="range" min="-100" max="100">
[[Rotation.y]]
</div>
<div>
<label for="zRotation">Z:</label>
<input id="zRotation" ng-model="Rotation.z" type="range" min="-100" max="100">
[[Rotation.z]]
</div>
</fieldset>
<fieldset>
<legend>Translation</legend>
<div>
<label for="xTranslation">X:</label>
<input id="xTranslation" ng-model="Translation.x" type="range" min="-100" max="100">
[[Translation.x]]
</div>
<div>
<label for="yTranslation">Y:</label>
<input id="yTranslation" ng-model="Translation.y" type="range" min="-100" max="100">
[[Translation.y]]
</div>
<div>
<label for="zTranslation">Z:</label>
<input id="zTranslation" ng-model="Translation.z" type="range" min="-100" max="100">
[[Translation.z]]
</div>
</fieldset>
</section>
<div id="zderp">
<div id="truck" style="-webkit-transform: rotateX([[Rotation.x]]deg) rotateY([[Rotation.y]]deg) rotateZ([[Rotation.z]]deg) translateX([[Translation.x]]px) translateY([[Translation.y]]px) translateZ([[Translation.z]]px)">
</div>
</div>
</section>
</section>
js
var app = angular.module('truck', []).config(function($interpolateProvider){
"use strict";
$interpolateProvider.startSymbol('[[').endSymbol(']]');
});
app.factory('Rotation', function(){
return {
x : '1',
y : '1',
z : '1'
}
});
function TruckCtl($scope, Rotation){
$scope.x = Rotation.x;
$scope.x = Rotation.y;
$scope.x = Rotation.z;
}
function Truck($scope, Rotation){
$scope.x = Rotation.x;
$scope.x = Rotation.y;
$scope.x = Rotation.z;
}

Related

AngularJS v1.5.5 Reset form not working for invalid input fields

I have the code below (or see the fiddle) and I try to reset form and clear all input fields too for each form.
With AngularJS version 1.2.1 is working fine! but in my app I using version 1.5.5 because I have other libraries for separating the nested forms in <md-tab> tags using material framework who need this version.
The problem is when any field it's invalid then reset does not work as expected and these fields remain unchanged instead to be clear.
There is another way to clearing all fields (of nested form) when I click reset button ?
angular.module("main", [])
.controller("register", function($scope) {
$scope.data = {
A: {},
B: {}
};
$scope.reset = function(form) {
form.$setPristine();
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<body ng-app="main">
<div ng-controller="register" class="form">
<form name="form" novalidate role="form">
<div class="form">
<h1>TAB1 - Form A:</h1>
<ng-form name="A">
A1:
<input type="text" ng-model="data.A.A1" ng-minlength="4" ng-maxlength="15" />A2:
<input type="text" ng-model="data.A.A2" ng-minlength="4" ng-maxlength="15" />
<button type="button" ng-disabled="A.$pristine" ng-click="reset(A); data.A=null;">Reset</button>
<br/>
<strong>A.$pristine =</strong> {{A.$pristine}}
<strong>A.$valid =</strong> {{A.$valid}}
</ng-form>
</div>
<br/>
<br/>
<div class="form">
<h1>TAB2 - Form B:</h1>
<ng-form name="B">
B1:
<input type="text" ng-model="data.B.B1" ng-minlength="4" ng-maxlength="15" />B2
<input type="text" ng-model="data.B.B2" ng-minlength="4" ng-maxlength="15" />
<button type="button" ng-disabled="B.$pristine" ng-click="reset(B); data.B=null;">Reset</button>
<br/>
<strong>B.$pristine =</strong> {{B.$pristine}}
<strong>B.$valid =</strong> {{B.$valid}}
</ng-form>
</div>
</form>
<h1>data:</h1>
<pre>{{data | json}}</pre>
</div>
</body>
It's because ng-model binds to the A and B objects by reference in $scope.data. If you remove the $scope.data.A = null from your ng-click and reset the object without creating a new one, it works:
https://jsfiddle.net/utwf604r/15/
$scope.reset = function (form)
{
// don't change the reference to A
// $scope.data.A = {} wont work!!
angular.extend($scope.data, {A:{A1:'',A2:''}, B:{B1:'',B2:''}});
form.$setPristine();
};

Convert user input into a label using angular.js

What I'am trying to do is convert every user input into a label using angular. I believe that I'am doing the right thing, but is not working. I will appreciate if somebody take a look at this code. Thank you
here is a plunker
<div class="row" ng-controller="tagForm">
<div ng-click="addEntry()">
<div class="col-xs-12 col-sm-12 col-md-10 ">
<input type="text" placeholder="What are your area of expertise" ng-model="newEntry.name" class="form-control border" />
</div>
<div class="col-xs-12 col-md-2 center form-button">
<input type="button" value="Add" class="btn btn-orange btn-add" />
</div>
<div class="col-md-8 col-sm-offset-2" id="up">
<br />
<span class="label label-primary" ng-repeat="entry in entries">{{entry.name}}</span>
</div>
</div>
</div>
app.controller('tagForm', ['$scope', function($scope) {
return $scope.addEntry = function() {
$scope.entries.push($scope.newEntry);
return $scope.newEntry = {};
};
}]);
You have a few things wrong in your Plunk, but here's some stuff to start with:
You need to wire up a click event on your Add button. Right now, its not doing anything when you click it
Bind to an ng-model on the scope just using 'newEntry'. All you're typing is a name so thats all you need to save on the scope.
Loop over entries, printing out just 'entry' instead of 'entry.name'
And your controller should look like this (no need for the returns)
app.controller('tagForm', ['$scope', function($scope) {
$scope.entries = [];
$scope.addEntry = function() {
$scope.entries.push($scope.newEntry);
};
}]);
See this fiddle:
http://jsfiddle.net/smaye81/anrv2qms/1/

Advice on the correct use of ngModel

I' new to AngularJS and have a following ambiguity with usage of ngModel. I want to give to the user possibility to generate unlimited number of "name": "value" pairs. So I generating div with ng-repeat for every element from pair. Here is my html:
<div ng-app>
<div ng-controller="TestCtrl">
<input type="button" value="+" ng-click="addNewRow();"/>
<div ng-repeat="a in range(itemsNumber)"><input type="text" name="key"/> : <input type="text" name="value"/></div>
</div>
</div>
And the JavaScript:
function TestCtrl($scope) {
$scope.itemsNumber = 1;
$scope.range = function() {
return new Array($scope.itemsNumber);
};
$scope.addNewRow = function () {
$scope.itemsNumber++;
}
};
Here is working js fiddle:
http://jsfiddle.net/zono/RCW2k/
I want to have model for this generating items but not sure how to do it.
I would appreciate any ideas and tips.
Best regards.
Edit:
I have create other solution. It can be viewed in this fiddle
http://jsfiddle.net/zono/RCW2k/8/
But is this solution is good idea?
Here is a fiddle: http://jsfiddle.net/RCW2k/13/
You should just create an array on the scope and it's also your model:
controller:
function TestCtrl($scope) {
$scope.items = [{key:"hello",value:"world"}]
$scope.addNewRow = function () {
$scope.items.push({key:"",value:""});
}
};
html:
<div ng-controller="TestCtrl">
<input type="button" value="+" ng-click="addNewRow();"/>
<div ng-repeat="item in items">
<input type="text" name="key" ng-model="item.key"/> :
<input type="text" name="value" ng-model="item.value"/>
</div>
</div>

How to validate form when the forms are inserted using ng-include

I have 3 different form pages which are inserted using ng-include into DOM within a bootstrap modal window. What is the best way to do validation in every form and do a complete form submit(for all the 3 forms) in scenario like this?
HTML
<div ng-switch on="page">
<div ng-switch-when="Games">
<div ng-include="'Games.html'"></div>
</div>
<div ng-switch-when="Music">
<div ng-include="'Music.html'"></div>
</div>
<div ng-switch-when="Videos">
<div ng-include="'Videos.html'"></div>
</div>
</div>
Demo : http://plnkr.co/edit/D1tMRpxVzn51g18Adnp8?p=preview
There is to find a way to validate data yet
(may be with jqueryvalidation) but can be a starting point.
I think there is no way to get the value of games.$valid
so I've thought of
var app = angular.module("myApp", [])
app.controller("FormsCtrl", function($scope) {
//console.log($scope);
// $scope.items = ['Games', 'Music', 'Videos'];
$scope.$on('someEvent',function(e,a){
console.log(a);
})
});
app.directive("myform", function() {
return {
restrict: "A",
link:function(scope,element,attrs){
element.bind('submit',function(e){
var isValid = false; // TO DO :)
scope.$emit('someEvent', [attrs.fname,isValid]);
});
}
}
});
<div ng-controller="FormsCtrl">
<div ng-switch on="page">
<div ng-switch-when="Games">
<div ng-include="'Games.html'"></div>
</div>
<div ng-switch-when="Music">
<div ng-include="'Music.html'"></div>
</div>
<div ng-switch-when="Videos">
<div ng-include="'Videos.html'"></div>
</div>
</div>
</div>
<form name="games" class="simple-form" myform fname="games">
<input type="text" ng-model="prefix.games.name" name="uName" required /><br>
</form>
EDIT
A smarter quicker way :)
app.controller("FormsCtrl", function($scope) {
$scope.mySubmit = function(isValid){
console.log(isValid);
}
});
<form name="games" class="simple-form" ng-submit="mySubmit(games.$valid)">
<input type="text" ng-model="prefix.games.name" name="uName" required /><br>
</form>

AngularJS: ng-model inside ng-repeat?

I'm trying to generate form inputs with ng-repeat.
Note: 'customFields' is an array of field names: ["Age", "Weight", "Ethnicity"].
<div class="control-group" ng-repeat="field in customFields">
<label class="control-label">{{field}}</label>
<div class="controls">
<input type="text" ng-model="person.customfields.{{field}}" />
</div>
</div>
What is the best/correct way to set 'ng-model'? I would like to send it to the server as person.customfields.'fieldname' where fieldname comes from 'field in customFields'.
<div ng-app ng-controller="Ctrl">
<div class="control-group" ng-repeat="field in customFields">
<label class="control-label">{{field}}</label>
<div class="controls">
<input type="text" ng-model="person.customfields[field]" />
</div>
</div>
<button ng-click="collectData()">Collect</button>
</div>
function Ctrl($scope) {
$scope.customFields = ["Age", "Weight", "Ethnicity"];
$scope.person = {
customfields: {
"Age": 0,
"Weight": 0,
"Ethnicity": 0
}
};
$scope.collectData = function () {
console.log($scope.person.customfields);
}
}
You can try it here.
Updated:
For the validation, the trick is to put <ng-form> inside the repeater. Please try.
It should be:
<input type="text" ng-model="person.customfields[field]" />
Any on who ends up here For ng-model inside ng-repeat
http://jsfiddle.net/sirhc/z9cGm/
the above link has good description on how to use it with examples
Try this
ng-model="person.customfields."{{field}}
Moved the double quotes

Resources