Nesting ng-model semantically - javascript

I have a very large model that I am creating a form for using AngularJS. It's nested over 4 levels deep and the names of the fields on the model are very long. I end up with markup like this.
<input type="text" ng-model="something_super_long.another_very_long_thing.hey_lets_add_another.ok_one_more._last_one_seriously"></input>
This is pretty annoying. I wish that I could set up some kind of nested inheritance to avoid setting super long ng-model names over and over. Here is a fully fleshed out EXAMPLE of what I am talking about. I made the model a REASONABLE level of depth only 3 levels of not so long names.
Instead of doing this.
<div ng-app="myApp">
<div ng-controller="myController">
<input type="text" ng-model="building_in_san_francisco.layout_floor_1.room_1" />
<input type="text" ng-model="building_in_san_francisco.layout_floor_1.room_2" />
<input type="text" ng-model="building_in_san_francisco.layout_floor_1.room_3" />
</div>
</div>
I want to do something more like this:
<div ng-app="myApp">
<div ng-controller="myController">
<div ng-model="building_in_san_francisco">
<div ng-model="layout_floor_1">
<input type="text" ng-model="room_1" />
<input type="text" ng-model="room_2" />
<input type="text" ng-model="room_3" />
</div>
</div>
</div>
</div>
Does anyone know if anything like this is possible?

You could use ng-init in the templates and nest scopes. This keeps your controller clean and uses the child scopes only in the template:
<div ng-app="myApp">
<div ng-controller="myController">
<div ng-scope ng-init="building = buildings.building_in_san_francisco">
<div ng-scope ng-init="floor = building.layout_floor_1">
<input type="text" ng-model="floor.room_1" />
<input type="text" ng-model="floor.room_2" />
<input type="text" ng-model="floor.room_3" />
</div>
</div>
</div>
</div>
JS
angular.module('myApp', [])
.controller('myController', function mainCtrl($scope) {
$scope.buildings = {
building_in_san_francisco: {
layout_floor_1: {
room_1: '1',
room_2: '2',
room_3: '3'
}
}
};
});

You can try this in your controller:
$scope.something=building_in_san_francisco.layout_floor_1;
And when you call it
<input type="text" ng-model="something.room_1" />

Related

How copy value of input text to other inputs texts

How copy value of input text to other Input texts elements in AngularJS 1.X
But each input has have his own property in controller
I've tried so far
<div class="paramWrap"> // copy from here
<label for="accoubntDis">Account Discount</label>
<input id="accoubntDis" type="text" class="form-control" ng-model="accoubntDis">
</div>
<pre>{{accoubntDis}}</pre> // only this displayed
<div class="space"></div>
<div class="paramWrap">
<label for="365Dis">O365 Exchange Unlicensed Discount</label>
<input id="365Dis" type="text" class="form-control" value="{{accoubntDis}}" ng-model="accoubntDis12">
</div>
<div class="space"></div>
<div class="paramWrap">
<label for="gSuiteO365">G Suite / O365 Exchange Paused/Archived</label>
<input id="gSuiteO365" type="text" class="form-control" value={{accoubntDis}} ng-model="gSuiteO365">
</div>
What I see actually that only the <pre>{{accoubntDis}}</pre> is displayed
why value/ng-value={{accoubntDis}}/"accoubntDis" not worked in <input .... ??
Do I need to use any JS functions on controller side for this ?
The simplest and best approach would be to use ng-change instead of ng-value.
HTML code:
<input type = "text" ng-model = "first" ng-change = "changeSecond()"/>
<input type = "text" ng-model = "second"/>
Angular: js corresponding code
$scope.changeSecond = function() {
$scope.second = $scope.first;
}
I tried with "ng-value", its working in angular 1.5 and above.
If you angular is below 1.5 you can go for below approach.
So better you write a function call on change of input field1, and in
that function assign the value of field1 to field2. Consider the below sample example.
HTML:
<input type="text" ng-model="data" ng-change="updateField()">
<input type="text" ng-model="meta">
JS:
$scope.data;
$scope.meta;
$scope.updateField= function(){
$scope.meta=$scope.data;
}
Use ng-value directive.
<input ng-value="accoubntDis" />
Refer to this API doc.
BTW, as you're using ng-model, value will be overridden so that it seems to be not working.
<input ng-model="accoubntDis" />
In input doesn't need the {{}}, just go with value="accoubntDis" will do.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="paramWrap"> // copy from here
<label for="accoubntDis">Account Discount</label>
<input id="accoubntDis" type="text" class="form-control" ng-model="accoubntDis" ng-change="calculate()">
</div>
<pre>{{accoubntDis}}</pre> // only this displayed
<div class="space"></div>
<div class="paramWrap">
<label for="365Dis">O365 Exchange Unlicensed Discount</label>
<input id="365Dis" type="text" class="form-control" ng-value="accoubntDis2">
</div>
<div class="space"></div>
<div class="paramWrap">
<label for="gSuiteO365">G Suite / O365 Exchange Paused/Archived</label>
<input id="gSuiteO365" type="text" class="form-control" ng-model="accoubntDis3">
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.accoubntDis = "100";
$scope.accoubntDis2 = $scope.accoubntDis * 2;
$scope.accoubntDis3 = $scope.accoubntDis / 2;
$scope.calculate = function(){
$scope.accoubntDis2 = $scope.accoubntDis * 2;
$scope.accoubntDis3 = $scope.accoubntDis / 2;
}
});
</script>
</body>
</html>
Use ng-value directive.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="paramWrap">
<label for="accoubntDis">Account Discount</label>
<input id="accoubntDis" type="text" class="form-control" ng-model="accoubntDis">
</div>
<pre>{{accoubntDis}}</pre>
<div class="space"></div>
<div class="paramWrap">
<label for="365Dis">O365 Exchange Unlicensed Discount</label>
<input id="365Dis" type="text" class="form-control" ng-value="accoubntDis" ng-model="accoubntDis12">
</div>
<div class="space"></div>
<div class="paramWrap">
<label for="gSuiteO365">G Suite / O365 Exchange Paused/Archived</label>
<input id="gSuiteO365" type="text" class="form-control" value={{accoubntDis}} ng-model="gSuiteO365">
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.accountDis = "Hello World!";
$scope.accoubntDis=123;
});
</script>
<p>This example shows how to use AngularJS expressions to set the value of an input field.</p>
</body>
</html>

AngularJS dynamically add input fields and keep reference to each

I am currently trying to figure out how to keep reference to individual dynamically added input fields. I have a modal popup as follows:
<div ng-controller="SamplesQueryController">
<button ng-click="toggleModal()" class="btn-splash-small">Add Sample</button>
<modal title="Create New Sample" visible="showModal">
<form role="form">
Sample Name:<br>
<input type="text" ng-model="newSampleName.sampleName">
<br> Attribute 1 Name:<br>
<input type="text" ng-model="newAtt1Name.att1Name">
<br> Attribute 1 Value: <br>
<input type="text" ng-model="newAtt1Value.att1Value"> <br>
<button id="submitSample" ng-click="createSample();toggleModal()">Submit
Sample</button>
<button id="addAttribute">Add Attribute</button>
<button ng-click="toggleModal()">Close</button>
</form>
</modal>
</div>
which currently has an input field for att1Name and att1Value, I have an addAttribute button which should add 2 new input fields (for att2Name and att2Value). I can dynamically create the inputs using a method such as:
<input type="text" ng-repeat="myinput in myinputs" ng-model="myinput">
</input>
but how can I keep reference to each of the typed in values in the input fields and how can I create 2 fields for each element in myinputs
Preferably, I would be storing these values in some sort of structure like attributes.att1.name, attributes.att1.value, attributes.att8.name, etc
You'll want to have your model as an Array that contains Objects, which has the property 'name' and 'value' initiated.
Then it's pretty easy to create a ng-repeat div, that contains 2 text input fields:
<div ng-repeat="input in inputs">
<input type="text" ng-model="input.l">
<input type="text" ng-model="input.v">
</div>
Then you can subsequently add the fields by pushing newly initiated object to the $scope.inputs.
function add() {
var obj = {attr1Name: '', attr1Value: ''};
$scope.inputs.push(obj);
}
Working fiddle here: https://jsfiddle.net/ccvLhmps/
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<h2>Cost Calculator</h2>
<p></p>
<p></p>
<p></p>
<div ng-app>
<input name="amount" ng-model="a" placeholder="Amount" />
<input name="adjustment" ng-model="b" placeholder="Adjustment" />
<input name="advance" ng-model="c" placeholder="Total" value='{{ a-b}}' />
<input name="balance" placeholder="Total" readonly required value='{{ a-b-c}}' />
</div>
</body>
</html>

Angular binding not working

I have this fiddle (which won't work, I don't know why. Will be glad if someone would help to fix it). The code in the fiddle is:
HTML:
<body ng-app="testApp">
<div ng-controller="AppCtrl">
<span>kid name is {{kids[0].name}}</span><br />
<input type="text" ng-model="kids[0].name" value={{kids[0].name}} > <br />
<span>kid age is {{kids[0].age}}</span> <br />
<input type="range" value={{kids[0].age}} >
<div ng-repeat="kid in kids">
<br />
The kid's name is <strong id="name">{{kid.name}}</strong> and his age is {{kid.age}}
<br />
<input type="range" value={{kid.age}} >
</div>
</div>
</body>
JS:
var testApp = angular.module('testApp', []);
testApp.controller('AppCtrl', function ($scope, $http)
{
$scope.kids = [{"name": "Din", "age": 11}, {"name": "Dina", "age": 17}];
});
The problem is that the range (age) input is not binded to the the span above it ("kid age is {{kid.age}}").
Why there is no binding?
Your fiddle was configured incorrectly. You should select "No wrap in " below the AngularJs version.
Here is the updated fiddle.
In addition to the change in setting, you also need to add ng-model to the range input like #nubinub suggested.
<input type="range" ng-model="kid.age" value="{{kid.age}}">
Change the onLoad to No Wrap in JSFiddle
Also use ng-model in input field for binding with the angularjs
change
<input type="range" value={{kid.age}} >
to
Take a look at this
Working Demo
<body ng-app="testApp">
<div ng-controller="AppCtrl">
<span>kid name is {{kids[0].name}}</span><br />
<input type="text" ng-model="kids[0].name" value={{kids[0].name}} > <br />
<span>kid age is {{kids[0].age}}</span> <br />
<input type="text" value={{kids[0].age}} >
<div ng-repeat="kid in kids">
<br />
The kid's name is <strong id="name">{{kid.name}}</strong> and his age is {{kid.age}}
<br />
<input type="range" ng-model="kid.age" value="{{kid.age}}">
</div>
</div>

Angularjs : add a dynamic attribute

i have data like this :
$scope.list = {
0:{'type':'text','required':true},
1:{'type':'text','required':false},
2:{'type':'text','required':true}
};
i'm using ng-repeat to create form
<div ng-repeat="l in list">
<input type="{{l.type}}" />
</div>
how I want to get the attributes "required" if the value of "l.required" is true
like this :
<div>
<input type="text" required />
</div>
<div>
<input type="text" />
</div>
<div>
<input type="text" required />
</div>
how I do that
Try:
<div ng-repeat="(k, l) in list">
<input type="{{l.type}}" ng-required="l.required" />
</div>
since it is an object that you are iterating through you would need to use the value of the iteration i.e (k, l) in list and use ng-required to set the required flag.

Bind two inputs so they display the same text even if one of them was changed by user

The jQuery code looks like this and works fine (probably it look a bit sorter, so please let me know and I'll change it either): jsFiddle
jQuery:
$('.inputs').on('keyup',function(){
$(this).parent().not(this).find('.inputs').val($(this).val());
}
);
HTML:
<div>
<input type="text" class="inputs" value="hello">
<input type="text" class="inputs" value="John">
</div>
How can I rewrite this code for knockout.js?
Thank you.
Take a look at the below code snippet which will work fine with ko.
var value = "Hello John";
var viewModel = {
Name: ko.observable(value)
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.0.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type="text" data-bind="value:Name" class="inputs" id="first">
<input type="text" data-bind="value:Name" class="inputs" id="second">
</div>
<span data-bind="text: Name"> </span>
Hope, You will do this with more data. In that case, Take a look at this sample which will let you know about how to support more data.
For more faqs visit jqfaq.com
Just bind it to the same observable:
HTML
<div>
<input type="text" class="inputs" id="first" data-bind="value:foobar,valueUpdate:'keyup'">
<input type="text" class="inputs" id="second" data-bind="value:foobar,valueUpdate:'keyup'">
</div>
ViewModel
function AppViewModel() {
this.foobar = ko.observable('hello');
}
ko.applyBindings(new AppViewModel());
I used the valueUpdate binding to update the inputs in real time instead of on blur (see also: https://stackoverflow.com/a/4391419/664108)

Categories

Resources