When the user clicks on a radio button I run:
$scope.clientClick = function() {
//do stuff
}
I have a form, and I would like half of the fields on the form to be cleared in the above method.
I have done:
$scope.clientClick = function() {
$scope.entry.first_name = '';
$scope.entry.last_name = '';
$scope.entry.email = '';
$scope.entry.tel = '';
$scope.entry.gender = '';
$scope.entry.job = '';
$scope.entry.age = '';
}
But is there an easier way rather than listing each field again?
Short answer
['first_name', 'last_name', ...].forEach(function (f) {
$scope.entry[f] = '';
});
Long answer
In JavaScript, properties can be accessed in two ways:
obj.prop
obj['prop']
You can keep a list of strings with the properties that you want to clear, and then just iterate over it clearing each in turn.
I'd suggest that if you have a dependency to the radio button then the view model should reflect that it could be cleared:
$scope.entry.dependant = { first_name: '' ... }
$scope.clientClick = function() {
$scope.entry.dependant = {};
}
function initObject(obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
switch(typeof obj[i]){
case 'string':
obj[i] = '';
break;
case 'number':
obj[i] = 0;
break;
}
}
}
}
Use this function. NEVER do this $scope.entry = {} or $scope.entry.name = null, it's safer and you won't get unnecessary errors when you have some parts of your code that expect a type. It's a lot easier just to set a string to "".
I would use $scope.entry = null or $scope.entry = {}.
Make code simple and readable.
I would have done some thing like Reset a model with angular.js:
$scope.initial = [
{
first_name : '',
last_name : '',
email : '',
tel : '',
gender : '',
job : '',
age : ''
}
];
Demo
$scope.clientClick = function() {
angular.copy($scope.initial, $scope.entry);
});
Related
Hello guys i am trying to clear my ng-model when i fire my change function but my problem that i don't want to delete all i want to exclude one item in the object.
function change() {
if (vm.location.type) {
angular.forEach(vm.location, function (value, index) {
delete vm.location;
});
}
}
so i don't want to delete the
vm.location.type
my
vm.location
has
vm.location.boundaries;
vm.location.region;
vm.location.address;
vm.location.name;
vm.location.nonVisitingRadius;
vm.location.visitingRadius;
See the code below,
var obj = { a:123, b:123, c:123 }
delete obj.a;
Hence obj will be like this {b:123, c:123}
Note: Dont need any for loop to delete property from object
Updated Answer:
var obj= {
a: 'aaa',
b: 'bbb',
c: 'ccc',
d: 'ddd'
};
var removeObj = function(obj, props) {
for(var i = 0; i < props.length; i++) {
if(obj.hasOwnProperty(props[i])) {
delete obj[props[i]];
}
}
};
removeObj (obj, ["a", "d"]);
i don't know if i understand correctly what you're asking, but if you want to clear all the fields of your object preserving only type and preserving the reference of the object with plain javascirpt (no libraries), loop over the fields and check if the i field is equal to type.
for(var i in model.location){
if(i !== 'type')
delete model[i];
}
with underscore.js you could define a default model like:
var defaultModel = {
location: {
region: '',
address: '',
name: '',
nonVisitingRadius: '',
visitingRadius: '',
type: 'defaultvalue'
}
}
and when ng-change is triggered inside the function
_.extend(model, defaultModel);
that will keep the default value for type and clear all the others.
You can do it this with a temporary object :
let tempLocation = {};
tempLocation.type = $scope.location.type;
$scope.location = tempLocation;
In my controller I have created $scope function which returns an array. That function uses data from view with ng-model directive and everything is working fine (when I call this function with the expression in the view I get returned data), except when I want to use that returned array in my controller, I simply get nothing.
Plunker
JS code:
app.controller('CalculatorCtrl', function($scope) {
$scope.deparature = {
'lat_1': '',
'lat_2': '',
'lat_3': '',
'long_1': '',
'long_2': '',
'long_3': ''
}
$scope.arrival = {
'lat_1': '',
'lat_2': '',
'lat_3': '',
'long_1': '',
'long_2': '',
'long_3': ''
}
$scope.select = {
'departure_1': '',
'departure_2': '',
'arrival_1': '',
'arrival_2': ''
}
$scope.depCoordinate = function() {
var cordLat = $scope.deparature.lat_1 + '/' + $scope.deparature.lat_2 + '/' + $scope.deparature.lat_3 + '/';
if ($scope.select.departure_1 === 'S') {
var temp = '-' + cordLat;
var CordLatS = Dms.parseDMS(temp);
} else {
var CordLatS = Dms.parseDMS(cordLat);
};
var cordLong = $scope.deparature.long_1 + '/' + $scope.deparature.long_2 + '/' + $scope.deparature.long_3 + '/';
if ($scope.select.departure_2 === 'W') {
var temp = '-' + cordLong;
var CordLongW = Dms.parseDMS(temp);
} else {
var CordLongW = Dms.parseDMS(cordLong);
};
return [CordLatS.toFixed(5), CordLongW.toFixed(5)];
}
var cord = $scope.depCoordinate();
var lati = cord[0];
console.log(lati);
/*I need to pass the array result to var p1. How I can do that?*/
$scope.distance = function () {
var p1 = new LatLon(50.06632, -5.71475);
var p2 = new LatLon(58.64402, -3.07009);
return p1.distanceTo(p2);
};
});
First, there are some things in your plunker that should be relevant here:
NEVER do this: <p>Test: {{ depCoordinate() }}</p>.
It will call your function several times causing several problems.
Don't use ng-init() for this kind of thing: <div class="list" ng-init="initWaves()">. It should be used only in specific cases (i.e. ng-repeat), check the docs.
Then.. If I understood your question well, you want to use the returned array in your view, so, if I'm correct, here is how-to:
$scope.array = [CordLatS.toFixed(5), CordLongW.toFixed(5)];
return $scope.array;
And in your view just use it:
{{ array }} // or whatever you want to do with it.
What do you mean that "I get nothing"? As far as I see, you wrote $scope.depCoordinate(); on init state of controller. When your controller is executed, that function will work immediately.
I think problem is that initial state. Because you don't have any data on first creation of controller. All of your variables are ''.
So, what you want to do exactly? You can use ngChange directive on your view layer with element which are updating that variables (deparature, arrival, select) with a function that is for watching updates. Then you need to write a function into your controller as follows;
$scope.watchChanges = function() {
var cord = $scope.depCoordinate();
var lati = cord[0];
};
I have two factories (because it is more readable) and one controller.
I do not know if it is possible, but I want to sent the result of the two factories in one variable.
code
vm.result = [];
vm.validate = validate;
function validate(password1, password2) {
vm.result = comparePasswordFactory.compare(password1, password2) + validNumberFactory.valid(password1);
return vm.result;
}
compare returns:
return {
color: 'green',
text: 'Passwords match',
validate1: 'true'
};
valid returns:
return {
text: 'Number should be between 12 and 45',
validate2: 'false'
};
I do not think what I wrote is correct.
But, is this possible and/or is it a good option ?
in order to validate using both functions you have to read and compare its validate1 / validate2 properties
var passwordOK = comparePasswordFactory.compare(password1, password2).validate1 === 'true';
var numberOK = validNumberFactory.valid(password1).validate2 === 'true';
vm.result = passwordOK && numberOK;
tip: better way would be to use boolean values instead of string, eg.
return {
validate: false
}
pro way: consider using consistent api in your factories, then you could do something like:
var validators = [comparePasswordFactory, validNumberFactory];
var isValid = true;
for(var i=0;i<validators.length;i++){
if(!validators[i].validate.call(this, password1, password2)){
isValid = false;
break;
}
}
vm.result = isValid;
then you could easily add another validator (notice that all factories must implement validate method)
I have a teamDetails array, within which is a squad array, within which are player objects. Each player object has an injured property which contains the value "true" or "false".
I want to write a function that loops through the array returning only players whose injured property evaluates to true.
This is what I have so far (not working):
$scope.injuredPlayerSearch = function() {
var injuredPlayers = [];
$scope.teamDetails.squad.forEach(function(o) {
if (o[injured] === true) {
injuredPlayers.push(o)
}
});
return injuredPlayers;
}
I can't see what's wrong with this. If anyone can, would appreciate some help.
You do not need to write any function. angular is there for you.
var injuredPlayers = $filter('filter')($scope.teamDetails.squad, {injured:true}, true);
Here $filter is angular filter. Do dependency inject to your controler or sevice where you are using.
For more about angular filter refer here
Note: 2nd true is for strict type checking. it is equivalent to injured===true
EDIT
For showing it to directly on view angular has much better solution.
{{teamDetails.squad | filter:{injured:true}:true}}
For use in view no need any dependency injection or controller.
If the iteration is within an array of array this is the correct implementation:
$scope.injuredPlayerSearch = function() {
var injuredPlayers = [];
$scope.teamDetails.forEach(function(t){
t.squad.forEach(function(o) {
if (o[injured] === true) {
injuredPlayers.push(o)
}
});
});
return injuredPlayers;
}
You could use filter to return players who are injured:
$scope.injuredPlayerSearch = function() {
return $scope.teamDetails.squad.filter(function(o) {
return o[injured];
});
}
try this
var injuredPlayers = [];
angular.forEach($scope.teamDetails.squad,function(s){
if (s.injured === true) {
injuredPlayers.push(s)
}
})
return injuredPlayers;
Use the javascript filter
var players = [{ id : 0 , injured : true},
{ id : 1 , injured : false},
{ id : 2 , injured : false},
{ id : 3 , injured : true},
{ id : 4 , injured : true}];
var injuredPlayers = players.filter(filterByInjured)
function filterByInjured(player) {
if ('injured' in player && typeof(player.injured) === 'boolean' && player.injured === true) {
return true;
}
}
console.log(injuredPlayers);
You did everything correct just left something
$scope.injuredPlayerSearch = function() {
var injuredPlayers = [];
angular.forEach($scope.teamDetails.squad,function(o) {
if (o[injured] === true) {
injuredPlayers.push(o)
}
});
return injuredPlayers;
}
I'm trying to construct a translated message by looping over an array of objects and then adding a new "message" property to that object containing the translated string. I see the correct message output while inside $translate.then(); but when I assign the message to the object it is undefined. What is the correct way to resolve the promise returned from $translate.then() and assign it to the "message" property?
//items.controller.js
function getItems() {
return itemsFactory.getItems()
.then(function (response) {
vm.items = initItemsList(response.activities);
});
}
function initItemsList(itemsList) {
for (var i = 0; i < itemsList.length; i++){
var activityType = itemsList[i].activityType;
switch (activityType){
case "HISTORY": {
var itemName = itemsList[i].item.itemName;
var itemVersion = itemsList[i].item.itemVersion;
$translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
vm.itemContent = content;
console.log(vm.itemContent); // correct message displayed.
});
break;
}
default: {
break;
}
}
itemsList[i].message = vm.itemContent; // undefined
}
return itemsList;
}
// translation.json
"activity : {
"HISTORY" : "History for {{ itemname }} {{ itemversion }}."
}
Promises are always resolved asynchronously. So the statement
itemsList[i].message = vm.itemContent;
, which is executed right after the switch, is executed before the callback passed to the $translate promise. Just move the statement to the callback:
$translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
vm.itemContent = content;
console.log(vm.itemContent);
itemsList[i].message = vm.itemContent;
});
As #Vegar correctly states, the code inside then is executed after the assignment so moving the assignment inside then function will take care of the problem. However, your itemsList will be returned from the function before all the translations are done so you will need to return a promise that resolves when all translations are done:
function initItemsList(itemsList) {
var allTranslations = [];
for (var i = 0; i < itemsList.length; i++){
var activityType = itemsList[i].activityType;
switch (activityType){
case "HISTORY": {
var itemName = itemsList[i].item.itemName;
var itemVersion = itemsList[i].item.itemVersion;
allTranslations.push($translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
vm.itemContent = content;
itemsList[i].message = vm.itemContent;
}));
break;
}
default: {
break;
}
}
}
return $q.all(allTranslations);
}
The caller of your function will have to do like:
initItemList(itemList).then(function(translatedList){
//Do stuff with translated list
});