Set a property of scope object dynamically in Angular Js - javascript

I am writing a generic method to get some data from a service and populate in the dynamic property name passed in the function. the value does gets assigned to the text box using angular.element assignment but does not gets populated in the model. following is the code.
<div class="input-group">
<input class="form-control" id="ImgRollover" name="ImgRollover" ng-model="contentEntity.imgRollover" placeholder="" readonly="readonly" type="text">
<div class="input-group-btn">
<button class="btn" type="button" ng-click="pickImage('contentEntity.imgRollover')">
</button>
</div>
here is my controller method which internally uses a service which sends back a promise
$scope.pickImage = function (attrModel) {
ImageSelector.selectImage().then(
function (value) {
//angular.element("#" + attrModel).val(value);
$scope[attrModel] = value;
});
};
attrModel is a property name in the scope object contentEntity but the name of the property is known ONLY dynamically via the method parameter.

<button class="btn" type="button" ng-click="pickImage('contentEntity', 'imgRollover')"></button>
$scope.pickImage = function (attrModel1, attrModel2) {
ImageSelector.selectImage().then(function (value) {
$scope.[attrModel1][attrModel2] = value;
});
};
should work

I know this has already been well answered but I wanted to make a dynamic property creator.
It splits attrModel by '.' and then edits $scope and adds and/or returns each property if it either exists already or not, we preserve the last key outside of the while loop so that the value just has to be appended to it.
$scope.pickImage = function (attrModel) {
ImageSelector.selectImage().then(
function (value) {
var parent = $scope,
current,
attribute,
attributes = attrModel.split('.');
while(attributes.length > 1 &&
(attribute = attributes.shift()) &&
(current = parent[attribute] || (parent[attribute] = {}))) {
parent = current;
}
current[attributes[0]] = value;
});
};
Of course, if you want to do it the angular way you'd have to use a service in order to do that, it could look like this
jsfiddle here
angular.module('myApp').service('ObjectWalker', function () {
var getNodeData = function (object, path) {
var parent = object,
current,
attribute,
attributes = path.split('.');
while(attributes.length > 1 &&
(attribute = attributes.shift()) &&
(current = parent[attribute] || (parent[attribute] = {}))) {
parent = current;
}
return [current, attributes[0]];
};
return {
set: function(object, path, value) {
var nodeData = getNodeData(object, path);
nodeData[0][nodeData[1]] = value;
},
get: function(object, path) {
var nodeData = getNodeData(object, path);
return nodeData[0][nodeData[1]];
}
};
})

There is already an answer but, just like to post something for dynamic properties...
<!DOCTYPE html>
<html>
<head>
<script src="https://code.angularjs.org/1.2.23/angular.js"></script>
<script type="text/javascript">
var value = 0;
function mainCtrl($scope) {
value++;
$scope.pickImage = function (attrModel) {
value++;
alert(attrModel)
$scope[attrModel] = value;
};
$scope.getValue = function(attrModel) {
return $scope[attrModel];
}
}
</script>
</head>
<body ng-app ng-controller="mainCtrl">
<input type="text" ng-model="test.obj" />
<br/>
<button ng-click="pickImage(test.obj)">test</button>
<br/>
display the value afoter button click,
note there is no single quote
<br/>
value: {{ getValue(test.obj) }}
</body>
</html>

Related

How to clear the value of an input if there is no results or if it has a null value?

I am trying to clear the value of an input depending if it finds or not an id, if it finds an existing id, js updates the value of an input, but if it doesn't it keeps the last one found but I need to have the value clear, can someone tell me what is wrong:
function driverdata(valueid)
{
var numero_id = valueid;
//console.log(valueid)
var idselect = document.getElementById('driver'+id_number).value;
document.getElementById("idinsearch"+ id_number).value = idselect;
//console.log(idselect);
var placa = document.getElementById("searchable"+idselect).value;
console.log(placa);
if (placa != null) {
document.getElementById("placa"+ id_number).value = placa;
} else {
document.getElementById("placa"+ id_number).value = "";
}
}
In the method driverdata you don't define variable id_number so it's undefined when you try get element by id
So if id_number is equal to the parameter of the method you can directly use it
moreover to clear value you are right it's elem.value = ""
withour yout html i can propose you the following one => your script run
function driverdata(numberId)
{
var idselect = document.getElementById('driver'+numberId).value;
document.getElementById("idinsearch"+ numberId).value = idselect;
var placa = document.getElementById("searchable"+idselect).value;
if (placa != null) {
document.getElementById("placa"+ numberId).value = placa;
} else {
document.getElementById("placa"+ numberId).value = "";
}
}
<div onclick="driverdata(1)">
click me<br/>
driver<input id="driver1" value="1"/><br/>
idinsearch<input id="idinsearch1"/><br/>
<div id="searchable1">
input that will be clear <input id="placa1" value="test"/>
</div>
</div>

Jquery converted to Javascript results in title undefined? How do I convert this properly?

I'm trying to convert my jquery back to Javascript, but for some reason it states that title is undefined. I'm not sure how to convert it properly or what to do to fix this issue.
Here is the current jquery code
update: function (e) {
var el = e.target;
var $el = $(el);
var val = $el.val().trim();
if (!val) {
this.destroy(e);
return;
}
if ($el.data('abort')) {
$el.data('abort', false);
} else {
this.todos[this.indexFromEl(el)].title = val;
}
this.render();
},
Here is the code from indexFromEl function
indexFromEl: function (el) {
var id = $(el).closest('li').data('id');
var todos = this.todos;
var i = todos.length;
while (i--) {
if (todos[i].id === id) {
return i;
}
}
},
So based off the code above, I tried to convert it myself, but I don't think I did it correctly.
update: function (e) {
var el = e.target;
var val = el.value.trim();
if (!val) {
this.destroy(e);
return;
}
if(val === 'abort') {
return false;
} else {
return this.todos[this.indexFromEl(el)].title = val;
}
this.render();
},
How do I convert the first code block from jquery to javascript? Also, I'm not sure how to edit the first line in the indexFromEl jquery code
Here is the jquery script
<script id="todo-template" type="text/x-handlebars-template">
{{#this}}
<li {{#if completed}}class="completed"{{/if}} data-id="{{id}}">
<div class="view">
<input class="toggle" type="checkbox" {{#if completed}}checked{{/if}}>
<label>{{title}}</label>
<button class="destroy"></button>
</div>
<input class="edit" value="{{title}}">
</li>
{{/this}}
</script>
Since the id for each li is being set in the HTML markup, rather than by jQuery:
<li {{#if completed}}class="completed"{{/if}} data-id="{{id}}">
// ^^^^^^^^^^^^^^^^
Once you have a reference to the element in Javascript, all you need to do is retrieve the id property from the dataset, eg:
li.dataset.id
To do that, in your indexFromEl function, use:
const id = el.closest('li').dataset.id;
Or if you like using destructuring to make things a bit more DRY:
const { id } = el.closest('li').dataset;
Also note that it would be much cleaner to use findIndex if you want to find an index in an array:
indexFromEl: function (el) {
const { id } = el.closest('li').dataset;
return this.todos.findIndex(todo => todo.id === id);
}
(though, the above will return -1 if no index is found, rather than undefined, as your current code does, if that's an issue)
In your query version, you didn't return anything. So why returning JavaScript version?
First try to find what is this.todos[this.indexFromEl(el)] using instanceof
If this.todos[this.indexFromEl(el)] is Element then you can set(as you're assigning val) title attribute by setAttribute()
So,
this.todos[this.indexFromEl(el)].setAttribute('title', val);

input value to object and then that object push to array

Hollow i have some issue and small problem
i have 3 input fields I need to get values on click from them assign them to object and that object push in to array
can somebody can help ore say where to look info I'm searching on MDN but I can't find correct topic whit examples
1)input value to object and then that object push to array
function $(e) {
return document.querySelector(e);
}
function $$(e) {
return document.querySelectorAll(e);
}
var startBtn = $("send");
startBtn.addEventListener('click', creatTask, false);
function creatTask() {
var addTaskName = $(".task-name"),
addCategory = $(".category"),
addTaskSatus = $(".status");
<!-- task.Taskname = addTaskName.value
task.Category = addCategory.value
task.Status = addTaskSatus.value........... ? -- >
var TaskListArray = [];
var task = {
Taskname: undefined,
Category: undefined,
Status: undefined
}
console.log(task)
}
document.write("message")
Link to jsfiddle with html and javascript
Try setting id or className selector at var startBtn = $("send"); defining TaskListArray outside of creatTask function; setting values directly at creation of task object; use Array.prototype.push() to add current task object to TaskListArray array.
Also, use window.onload event, or place <script> after elements in html for elements queried in DOM to be loaded in document before creatTask is called or startBtn defined
<script>
window.onload = function() {
function $(e) {
return document.querySelector(e);
}
function $$(e) {
return document.querySelectorAll(e);
}
var startBtn = $(".send");
var TaskListArray = [];
startBtn.addEventListener('click', creatTask, false);
function creatTask() {
var addTaskName = $(".task-name"),
addCategory = $(".category"),
addTaskSatus = $(".status");
var task = {
Taskname: addTaskName.value,
Category: addCategory.value,
Status: addTaskSatus.value
}
TaskListArray.push(task)
console.log(task)
}
}
// document.write("message")
</script>
<input class="task-name" name="task" />
<br>
<input class="category" name="category" />
<br>
<input class="status" name="status" />
<br>
<input type="button" class="send" value="send" />

Form functionality lost in ng-if

I have a simple form with a checkbox which clicked deletes a property from an object.
Here is the controller:
app.controller('PropController', function ($scope) {
var str = '{"meta":{"aprop":"lprop"},"props":{"gprop":12,"lprop":9,"wrop":5}}';
$scope.filecontent = JSON.parse(str);
$scope.delprop = false;
$scope.propobj = $scope.filecontent.props;
$scope.proptodel = $scope.filecontent.meta.prop;
var mainvalue = $scope.propobj[$scope.proptodel];
$scope.$watch('delprop', function () {
if ($scope.delprop == true) {
delete $scope.propobj[$scope.proptodel];
} else {
$scope.propobj[$scope.proptodel] = mainvalue;
}
});
And the view:
<div ng-app="SomeProperties" ng-controller="PropController">
<div ng-if="proptodel">
there is a property to delete: {{proptodel}}
<form><input type="checkbox" ng-model="delprop"></form>
filecontent: {{filecontent}}
</div>
<div ng-if="!proptodel">
there is NO property to delete
</div>
</div>
The app on jsfiddle.
The problem appears when the form is in the ng-if, it stops behaving. As you can try it in the jsfiddle, when I delete ng-if="proptodel" from the div containing the form, it working normally. What is the explanation of this?
You need to put the delprop into in object to make ng-model work properly. That means your markup should have:
<form><input type="checkbox" ng-model="obj.delprop"></form>
And your Javascript code should look like:
$scope.obj = {
delprop: false
};
$scope.propobj = $scope.filecontent.props;
$scope.proptodel = $scope.filecontent.meta.prop;
var mainvalue = $scope.propobj[$scope.proptodel];
$scope.$watch('obj.delprop', function () {
if ($scope.obj.delprop == true) {
delete $scope.propobj[$scope.proptodel];
} else {
$scope.propobj[$scope.proptodel] = mainvalue;
}
});
Of course you should find a proper name for the object as obj is really bad and generic ;-)

Angular edit a copy of a copy

I'm having a few problems editing a copy of a copy.
When you first edit a record it is assigned to a $scope.original and a copy is taken for editing and stored in $scope.copy which can be changed and saved back to $scope.original which in-turn updates $scope.something correctly.
The problem is while editing the first record if you then take a copy of one of the values for further editing, it doesn't get updated when the $scope.saveSomething() function is called.
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.Something = [{
name: "Aye",
desc: new Date()
}, {
name: "Bee",
desc: new Date()
}, {
name: "See",
desc: new Date()
}];
//=================== First copy
$scope.edit = function(what) {
$scope.original = what;
$scope.copy = angular.copy(what);
}
$scope.save = function(copy) {
angular.copy($scope.copy, $scope.original);
$scope.cancel();
}
$scope.cancel = function() {
$scope.copy = null;
}
//=================== Second copy
$scope.editName = function(what) {
$scope.originalName = what;
$scope.copyName = angular.copy(what);
}
$scope.saveName = function() {
angular.copy($scope.copyName, $scope.originalName);
$scope.cancelName();
}
$scope.cancelName = function() {
$scope.copyName = null;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="s in Something">
<pre>{{s | json}}</pre>
<a ng-click='edit(s)'>edit</a>
<br/>
<br/>
</div>
<input type='text' ng-model='copy.name' />
<input type='text' ng-model='copy.desc' />
<br/>
<button ng-click='save(copy)' ng-disabled="!copy">save</button>
<button ng-click='cancel()' ng-disabled="!copy">cancel</button>
<a ng-click='editName(copy.name)'>edit name</a>
<br>
<br>
<input type='text' ng-model='copyName' />
<br>
<button ng-click='saveName()' ng-disabled="!originalName">saveName</button>
<button ng-click='cancelName()' ng-disabled="!originalName">cancelName</button>
</div>
</div>
I'm fairly new to Angular, and have been scratching my head on this one for a while now, any ideas why?
Edit
Updated the code to give a better example, the first version suggested that you might know which value of the first edit's values you were editing, and the solution scarlz posted ( http://jsfiddle.net/Karl33to/w23ppp9r/ ) just sets that value directly in the second save function, but I need to be able to do the second edit on any of the values that the first edit loads.
Have also created a fiddle if that's easier for you to run / fork http://jsfiddle.net/w23ppp9r/2/
Your problem arises from your use of angular.copy. In $scope.saveName, your destination $scope.originalName is a string, which will result in angular throwing an error.
There is actually no reason to use angular.copy at all if you're working with primitives. Instead, you could use the following here:
$scope.editName = function(what) {
$scope.originalName = what;
$scope.copyName = what;
};
$scope.saveName = function() {
$scope.copy.name = $scope.copyName;
$scope.cancelName();
}
I've managed to come up with a simple solution, which seems to work.
Instead of passing the primitive to the second edit function, if I pass in the key and a copy of the object instead, I can then update the first copy correctly.
Here's a working fiddle http://jsfiddle.net/w23ppp9r/3/
... and the relevant bit of code:
//=================== Second copy
$scope.editSomething = function(key, obj) {
$scope.originalKey = key;
$scope.originalObj = obj;
$scope.copyVal = obj[key];
};
$scope.saveSomething = function(newVal) {
$scope.originalObj[$scope.originalKey] = newVal;
$scope.cancelEdit();
}
$scope.cancelEdit = function() {
$scope.originalKey = null;
$scope.originalObj = null;
$scope.copyVal = null;
}
Is there a better answer?

Categories

Resources