how to pass value from angularjs template to controller? - html

HTML code:
<tr ng-repeat="x in products">
{{x.product_name}}
i just want to get this {{x.product_name}}, in angularjs scope.
means, if i click on any of the button, it should pass the x.product_name to angularjs in controller. How to do this?
I am new to angularjs.
Thank you in advance.

Put your code inside ng-app and assign ng-controller.
Make sure to add products property on $scope of controller
Make sure each product contains product_name
angular.module('myApp', [])
.controller('myController', ['$scope', function myController($scope) {
$scope.products = [{
product_name: 'cellphone'
}, {
product_name: 'laptops'
}, {
product_name: 'desktops'
}];
$scope.handleClick = (productName) => {
console.log(`${productName} clicked`);
}
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<table>
<tr ng-repeat="x in products">
<td>
{{x.product_name}}
</td>
</table>
</div>

Related

Angular JS - Focus on dyamically created text box

I have a table in which one item is editable. On clicking that item, the text changes to a text box and it can be edited. The issue is, on clicking the text, the text changes to textbox but I'm not able to focus on the textbox.
This is the code
JS
$scope.togglePrice = function (item) {
item.showUpdatePrice = true;
}
HTML
<a ng-click="togglePrice(item)" ng-hide="item.showUpdatePrice" style="text-decoration:underline; cursor:pointer;">{{item.sellingPrice | currencyFormat}}</a>
<input id="updatePriceId" ng-model="item.sellingPrice" class="form-control" ng-class="{'errorClass': showPriceError}" ng-show="item.showUpdatePrice" ng-blur="saveUpdatedPrice(item)" type="text" placeholder="Enter Price">
Edit
<tbody ng-repeat="item in shoppingItems">
<tr>
<td class="priceDiv">
<div>
<a ng-click="togglePrice(item)" ng-hide="item.showUpdatePrice" style="text-decoration:underline; cursor:pointer;">{{item.sellingPrice | currencyFormat}}</a>
<input ng-model="item.sellingPrice" auto-focus class="form-control" ng-class="{'errorClass': showPriceError}" ng-show="item.showUpdatePrice" ng-blur="saveUpdatedPrice(item)" type="text" placeholder="Enter Price">
</div>
</td>
</tr>
</tbody>
You should make a small change to your method and should add one directive to achieve your solution.
$scope.togglePrice = function (item) {
item.showUpdatePrice = !item.showUpdatePrice;
}
In this solution, on click on the text-boxes, the respective textbox gets focussed, and on blur or clicking outside, it gets unfocussed.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="myApp">
Click to focus on Below TextBoxes:
<table ng-controller="myCtrl">
<tbody ng-repeat="item in shoppingItems">
<tr>
<td class="priceDiv">
<div>
<a ng-click="togglePrice(item)" ng-hide="item.showUpdatePrice" style="text-decoration:underline; cursor:pointer;">{{item.sellingPrice}}</a>
<input ng-model="item.sellingPrice" auto-focus class="form-control" ng-class="{'errorClass': showPriceError}" ng-show="item.showUpdatePrice" ng-blur="saveUpdatedPrice(item)" type="text" placeholder="Enter Price" focus-me="item.showUpdatePrice">
</div>
</td>
</tr>
</tbody>
</table>
<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.togglePrice = function (item) {
item.showUpdatePrice = !item.showUpdatePrice;
}
$scope.shoppingItems = [
{
"showUpdatePrice" : false,
"sellingPrice" : "10"
},
{
"showUpdatePrice" : false,
"sellingPrice" : "20"
},
{
"showUpdatePrice" : false,
"sellingPrice" : "30"
},
]
});
app.directive('focusMe', ['$timeout', '$parse', 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();
});
}
});
element.bind('blur', function () {
scope.$apply(model.assign(scope, false));
});
}
};
}]);
</script>
</body>
</html>
PLEASE RUN THE ABOVE SNIPPET
Here is a working DEMO
Update your code with below code, may be it helps you. It will add a unique id to your inputs according to index. So you can simply access them using most efficient javascript selector.
Change your javascript to
$scope.togglePrice = function (item, buttonClicked) {
item.showUpdatePrice = true;
setTimeout(function(){
document.getElementById(buttonClicked).focus();
});
}
And in html
<tbody ng-repeat="item in shoppingItems">
<tr>
<td class="priceDiv">
<div>
<a ng-click="togglePrice(item, $index)" ng-hide="item.showUpdatePrice" style="text-decoration:underline; cursor:pointer;">{{item.sellingPrice | currencyFormat}}</a>
<input id='{{$index}}' ng-model="item.sellingPrice" auto-focus class="form-control" ng-class="{'errorClass': showPriceError}" ng-show="item.showUpdatePrice" ng-blur="saveUpdatedPrice(item)" type="text" placeholder="Enter Price">
</div>
</td>
</tr>
</tbody>
Try this May be it helps you. Thanks

angularjs post web service dropdown

I have created a web application with Eclipse where I use AngularJS and REST GET web services. Through the web services I query my MySQL database for data and send the values to my html page through controlles http GET controllers.
I successfully show dropdown lists with the database values in my HTML page. Now I want to send the selected items for each dropdown list back to a java page so that I can create a new query that will produce some new data. But I don't know how I can do this second part, can someone help me with it?
Thanks in advance!
this is part of my html page
<div id="three" ng-controller="mycontroller">
<table class="table table-hover">
<tbody>
<select ng-model="selecteditem">
<option ng-repeat="item in items">
{{item.itemname}}
</option>
</select>
</tbody>
</table>
<b>You selected: {{selecteditem}}</b>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('showitems', function($scope, $http) {
$http.get('http://localhost:8080/myproject/REST/WebService_items/GetItems').
success(function(data) {
$scope.items = data;
})
.error(function() {
$scope.items = "error in fetching data";
});
});
</script>
Thanks for both answers! My main issue is not how to show the items in the drop down lists, I have done that. I want to send the selected items to a Java page of my project through a REST web service function, so I don't know how to write the angularjs code in my HTML page that will send push/post the items in the web service's URL.
<label>example</label>
<md-select id="example" ng-model="vm.list.example" required>
<md-option ng-repeat="unit in vm.list" value="{{example.id}}">{{example.name}}</md-option>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="three" ng-controller="mycontroller">
<table class="table table-hover">
<tbody>
<select ng-model="selecteditem">
<option ng-repeat="item in items">
{{item.itemname}}
</option ng-click="callTheFunction(item.itemname})">
</select>
</tbody>
</table>
<b>You selected: {{selecteditem}}</b>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('mycontroller', function($scope, customService) {
$scope.items = [{itemname:'apple'},{itemname:'mango'}]
$scope.callTheFunction=function(itemSelected){
customService.restCallToJava(itemSelected)
}
app.service('customService',['$http', function($http) {
var restCallToJava= function(sensorObj){
return $http.post('/api',sensorObj);
}
}])
</script>

AngularJS ng-click seems to not work

I have an md-select that has inside it an md-option. In the md-option tag I have an ng-click that points to my function that is defined. The problem is that it seems to never get to my function when I click an option from the list.
Here is my html:
<div class="panel-body">
<md-select placeholder="{{getIntervalName()}}" ng-model="intervalSelected">
<md-option ng-repeat="item in intervals" value="{{item.name}}" ng-click="changeInterval(item)">
{{item.name}}
</md-option>
</md-select>
<div style="overflow: auto;">
<div id="parentDivChart" style="{{changeWidth()}};height:400px">
<canvas id="bar" class="chart chart-bar" chart-data="datta"
chart-labels="labels" chart-options="myoptions" chart-legend="legend">
</canvas>
<div tc-chartjs-legend chart-legend="legend"></div>
</div>
</div>
</div>
And this is my function defined in the controller:
function changeInterval(item) {
console.log("change intervaaaalll");
$scope.default_interval ="day";
intrvl = item.value;
setItem("interval", item.value);
$scope.loadChart();
};
It does not write to the console anything, that means it never reaches my function. Does anybody have an idea why ?
Thanks in advance!
It would have been better if you had provided the code where you create the controller.
However, I think you should create the method changeInterval(item) in this way:
var nameOfYourApp = angular.module(‘nameOfYourApp’, []);
nameOfYourApp.controller('nameOfYourController', function($scope) {
$scope.changeInterval = function(item) {
console.log("change intervaaaalll");
$scope.default_interval ="day";
intrvl = item.value;
setItem("interval", item.value);
$scope.loadChart();
}
});
Hope this helps!
As you want to use the changeInterval method on the scope you have to add it to the scope as follows:
In the controller:
$scope.changeInterval(item) {
console.log("change intervaaaalll");
$scope.default_interval ="day";
intrvl = item.value;
setItem("interval", item.value);
$scope.loadChart();
};
Don't forget to include $scope as a dependency for your controller.
E.g.:
app.controller('myCtrl', function($scope) {
});
Now as the changeInterval function is assigned to a variable on the scope it can be invoked on the view.
Since you changeInterval() is a private function to the controller, you can't access it. You need to make it public (bind it to a variable of the controller).
You should go with this approach:
$scope.changeInterval = changeIntervalapproach;
If you're using the view model approach with controllerAs then use:
vm.changeInterval = changeInterval;
Write "$scope.changeInterval=changeInterval;" in your controller
or
use "$scope.changeInterval=function (item) {...};"

How to create a separate scope isolated from ng-repeat in Angular?

I am new to AngularJS and have some trouble understanding the concept of scope in Angular. I have read some posts on stackoverflow as well as online articles, which advise me to create a custom directive to create an isolate scope, but I am getting nowhere...
As for the project I'm working on, I am trying to make a button that when clicked, will trigger a textarea. However, because of ng-repeat, the textarea is triggered for all buttons while I click only one.
My .js file:
angular.module('myApp')
.controller('myCtrl', function ($scope, Question) {
scope.visible = false;
scope.toggle = function() {
scope.visible = !scope.visible;
};
.directive("myDirective", function () {
return {
scope: {
ngClick: '&',
ngShow: '&'
}
}
});
Here is my HTML file:
<ul>
<li ng-repeat="object in objectList">
<button type="text" myDirective ng-click="toggle()">Click</button>
<textarea myDirective ng-show="visible"></textarea>
</li>
</ul>
Angular is creating child (NOT isolated) scope when ng-repeating, try this out, when you ng-init a variable, it is only visible within that repeat div.
<div ng-repeat="i in [0,1,2,3,4,5,6,7,8,9]" ng-init="visible=false">
<button ng-click="visible=!visible">Toggle</button>
<h1 ng-show="visible">look at me!</h1>
</div>
Plunker
There is no need to use a directive. You need to use object in the foreach to refer each item in the loop.
Add visible to each object in objectList:
$scope.objectList = [
{ visible: false },
{ visible: false },
{ visible: false }
];
Then the toggle button will need to pass the object to toggle:
$scope.toggle = function (object) {
object.visible = !object.visible;
};
The ng-show will need to check object.visible and ng-click will need to pass the object:
<button type="text" ng-click="toggle(object)">Click</button>
<textarea ng-show="object.visible"></textarea>
Plunkr

Angular ng-repeat with nested json objects?

I have a JSON object, represented as such:
{
"orders" : [
{
"ordernum" : "PRAAA000000177800601",
"buyer" : "Donna Heywood"
"parcels" : [
{
"upid" : "UPID567890123456",
"tpid" : "TPID789456789485"
},
{
"upid" : "UPID586905486090",
"tpid" : "TPID343454645455"
}
]
},
{
"ordernum" : "ORAAA000000367567345",
"buyer" : "Melanie Daniels"
"parcels" : [
{
"upid" : "UPID456547347776",
"tpid" : "TPID645896579688"
},
{
"upid" : "UPID768577673366",
"tpid" : "TPID784574333345"
}
]
}
]
}
I need to do a repeater on the second level of this, a list of the "upid" numbers.
I know already how to get the top level
<li ng-repeat="o in orders">{{o.ordernum}}</li>
But I am unclear on the sequence to loop a level down. For example, this is wrong:
<li ng-repeat="p in orders.parcels">{{p.upid}}</li>
I also know how to nest repeaters to get this, but in this case i don't need to display the top level at all.
CLARIFICATION
The goal here is to have one list with the 4 "upid" numbers (there are 2 for each parcel, and there are 2 parcels in the order).
Actually its same answer of #sylwester. The better way to put it in filter. And you can reuse it by passing propertyName parameter.
In your case we passed parcels
JS
myApp.filter('createarray', function () {
return function (value, propertyName) {
var arrayList = [];
angular.forEach(value, function (val) {
angular.forEach(val[propertyName], function (v) {
arrayList.push(v)
});
});
return arrayList;
}
});
HTML
<ul>
<li ng-repeat="o in ordersList.orders | createarray: 'parcels'">{{o.upid}}</li>
</ul>
Here is working Fiddle
You can just create new array 'parcels' like in demo below:
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
$scope.data = {
"orders": [{
"ordernum": "PRAAA000000177800601",
"buyer": "Donna Heywood",
"parcels": [{
"upid": "UPID567890123456",
"tpid": "TPID789456789485"
}, {
"upid": "UPID586905486090",
"tpid": "TPID343454645455"
}]
}, {
"ordernum": "ORAAA000000367567345",
"buyer": "Melanie Daniels",
"parcels": [{
"upid": "UPID456547347776",
"tpid": "TPID645896579688"
}, {
"upid": "UPID768577673366",
"tpid": "TPID784574333345"
}]
}]
};
$scope.parcels = [];
angular.forEach($scope.data.orders, function(order) {
angular.forEach(order.parcels, function(parcel) {
$scope.parcels.push(parcel)
})
})
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<ul>
<li ng-repeat="o in parcels">{{o.upid}}</li>
</ul>
</div>
</div>
Seems like you just need a double-nested for loop -
<ul>
<div ng-repeat="o in orders">
<li ng-repeat="p in o.parcels">{{p.upid}}</li>
</div>
</ul>
The HTML might be a little ugly here, but I'm not sure what exactly you are going for. Alternatively you could just create a new array of the parcels via mapping.
Searching a lot for nice and simple solution for iterating dynamically. I came up with this
JAVASCRIPT (angular): a person is an example of nested object. the is_object function will be use in the HTML view.
$scope.person = {
"name": "john",
"properties": {
"age": 25,
"sex": "m"
},
"salary": 1000
}
// helper method to check if a field is a nested object
$scope.is_object = function (something) {
return typeof (something) == 'object' ? true : false;
};
HTML: define a template for simple table. the 1st TD is the key which is displayed. another TD (2 or 3, but never both) will be show the value if its not an object (number / string), OR loop again if its an object.
<table border="1">
<tr ng-repeat="(k,v) in person">
<td> {{ k }} </td>
<td ng-if="is_object(v) == false"> {{ v }} </td>
<td ng-if="is_object(v)">
<table border="1">
<tr ng-repeat="(k2,v2) in v">
<td> {{ k2 }} </td>
<td> {{ v2 }} </td>
</tr>
</table>
</td>
</tr>
</table>
The reason that <li ng-repeat="p in orders.parcels">{{p.upid}}</li> does not work the way you expect is because the parcels array is an object inside each individual order in your order array, i.e. it is not an object of the orders array itself.
If your orders array is defined on the $scope of a controller, then you create the array on the $scope variable:
$scope.allParcels = $scope.orders
.map(function (elem) {
return elem.parcels;
}) // get an array where each element is an array of parcels.
.reduce(function (previousValue, currentValue) {
return previousValue.concat(currentValue);
}); // concat each array of parcels into a single array of parcels
then on the template, you can use <li ng-repeat='p in allParcels'>{{p.upid}}</li>
If, however, you do not want to place the array on the $scope, I believe you can do something similar to this:
<li ng-repeat="p in orders
.map(function (elem) {
return elem.parcels;
})
.reduce(function (previousValue, currentValue) {
return previousValue.concat(currentValue);
})">{{p.upid}}</li>
although I'm not 100% sure that Angular will evaluate the .map/.reduce in the ng-repeat expression (also having an array generated this way in an ng-repeat is ill-advised since angular would have to constantly generate a new array via map/reduce on each $digest cycle).