Angular.js model not updateing after first time - javascript

I have an example here:
http://www.search-this.com/examples/angular-help/
If you double-click "Text Message" in the list it brings up an input box.
type "one" in the input box and click the update button.
Notice the console.log
click SmsResponseActionParmAndValue to expand and locate the "Text Message" option
click ParmAndValue to expand and notice the Value property has our "one" value we typed in.
Now type two in the input box and look at the console.log and notice it doesn't update? It only updates the first time?
Help please...

which is getting updated in selected object not in main JSON object.
$scope.updateDetails = function () {
console.log("update");
console.log($scope.actions); //
console.log($scope.selectedAction); // look in this object updated you have to override it to original object or use 2 times ng-repeat to bind.
};

This is very ugly i know but its a solution:
$scope.updateDetails = function() {
angular.forEach($scope.actions.SmsResponseActionParmAndValue,function(action){
if(action.Description === $scope.selectedAction.Description){
console.log($scope.selectedAction)
action.ParmAndValue = $scope.selectedAction.ParmAndValue
return;
}
});
console.log($scope.actions)
};
The problem is that the updated model doesn't point to the same array in memory as the original object so we have to update the array that the original object points to.

Related

How to get checkbox value from localStorage

There is a page with a lot of different checkbox questions which then get submitted and populate the next page, this page however gets refreshed and the already annoyed potential client needs to go back and fill out the form again.
Now I have localstorage set up so he doesn't need to reselect all the checkbox again, he just needs to resubmit the form and his back in action.
How does one keep the values populated on the problem page so this fella doesn't have to go back to resubmit?
//SIZE SAVE
function save() {
localStorage.setItem('100', checkbox.checked);
var checkbox = document.getElementById('100');
localStorage.setItem('200', checkbox.checked);
var checkbox = document.getElementById('200');
//SIZE LOAD
function load() {
var checked = JSON.parse(localStorage.getItem('100'));
document.getElementById("100").checked = checked;
var checked = JSON.parse(localStorage.getItem('200'));
document.getElementById("200").checked = checked;
//THIS PAGE NEEDS THE CHECKMARK
echo get_site_url().
"/the/checkmark/selected/was/".$_POST['check_group'].
"/.png";
}
I think is much simple for now and especially for the feature if you write some code to make the management for all checkboxes form your form.
First of all it will be best if you group all your checkboxes into a single place.
Into a function like this you can declare all your checkbox selectors you want to save into the localStoarge (now you don't need to make variables for each selector into multiple places into your code)
function getCheckboxItems() {
return ['100', '200']
.map(function(selector) {
return {
selector: selector,
element: document.getElementById(selector)
}`enter code here`
});
}
Then to make things much simpler you can store all the values from the checkbox into a single object instead of save the result in multiple keys, in this way is much simpler to make management (let's say you want to erase all values or to update only a part)
The following function will take as argument all checkbox items from the function above, the point is the function above will return an array with the checkbox id and the checkbox element, than you just reduce all that array into this function into an single object containing all the ids and values, after this you just store the object into the localStorage
function serializeCheckboxes(elements) {
var container = elements.reduce(function (accumulator, item) {
accumulator[item.selector] = item.element.checked;
return accumulator;
}, {})
localStorage.setItem('container', JSON.stringify(container));
}
function save() {
var elements = getCheckboxItems();
serializeCheckboxes(elements);
}
After this you need another function who will read all the values from the localStorge and place them into your checkbox "checked" state
function readCheckboxes() {
var storage = localStorage.getItem('container'), //Your key
container = (storage) ? JSON.parse(storage) : {};
Object.keys(container).forEach(function(key) {
var element = document.getElementById(key);
if(element) {
element.checked = container[key];
}
});
}
This is just a simple service who can manage your problem but I think, for any additional changes you can customize this solution much simpler instead of keeping all into multiple variables, also if you add more checkbox elements into your application with this solution you just add the corresponding id into the array from the first function.
A live example here:
https://jsbin.com/xejibihiso/edit?html,js,output
localStorage has two main functions, getItem and setItem. For setItem you pass in a key and a value. If you write to that key again, it will rewrite that value. So in your case, if a box is checked you would do
localStorage.setItem("checkbox_value", true)
and when it is unchecked you would pass in false instead. To get the value you can look at using jQuery like so:
$(checkbox).is(':checked')
and use a simple if-else clause to pass in true or false. then when you reload your page, on $(document).ready() you can get the values using
localStorage.getItem(key)
and use JavaScript to set the check boxes values.
localStorage only allows you to store strings. What you can do is use a loop to create a string that has all the check boxes values separated by some delimiter. So, for example, if there are four check boxes with values true false false true your string would be "true\nfalse\nfalse\ntrue" where \n is the delimiter. then you can store that string in localStorage and when you retrieve it you can put all the values into an array like so:
array = localStorage.getItem(key).split('\n').
Then you can populate your check boxes with that newly retrieved array. Ask if anything needs clarification.

IN CQ, how to set value of all the items in Panel to blank

In ExtJS panel I need to set value of all items (e.g. textfield, pathfield) to blank. I don't want to set value of each individual item to blank but of whole panel in one go.
I am able to get list of items
function getAllChildren (panel) {
/*Get children of passed panel or an empty array if it doesn't have thems.*/
var children = panel.items ? panel.items.items : [];
/*For each child get their children and concatenate to result.*/
CQ.Ext.each(children, function (child) {
children = children.concat(getAllChildren(child));
});
return children;
}
but how to set to blank for whole panel? Please suggest what need to be done in this case.
Actually, it's not possible to do it with one liner - all at the same time. What your method returns is purely an array of objects. In fact if such syntax existed, it would iterate over all fields anyway.
Though clearing all fields, having the method you've proposed is very trivial to do. Just iterate over them all and call reset method. Mind some (especially custom) widgets might not handle it.
var fields = getAllChildren(panel);
CQ.Ext.each(fields, function(field) {
if (child.reset) {
child.reset();
}
});
You've got similar loop in your getAllChildren code - you might reset field at the same place.
The method is defined in Field type which is usually a supertype of each dialog widget. You can read more here.

EmberJS - Prevent record with duplicate attributes being added to store

My first question here so please accept my apologies if this has been asked before and/or I am making some newbie mistake!
I am trying to get my head around EmberJS with a simple exercise. I am trying to create a list of keywords and I have the basic functionality working. I wish to allow the user to enter a comma separated list of keywords to the store, however, alert if the keyword is a duplicate.
So I have an ArrayController with an Actions object and within which I have a createKeyword function.
createKeyword: function() {
// Get the keyword title set by the "New Keyword" text field
var entered_value = this.get('newKeyword');
if (!entered_value) { return false; }
if (!entered_value.trim()) { return; }
var entered_values = entered_value.split(",");
for ( var i=0; i<entered_values.length; i++){
var value = entered_values[i];
value = value.replace(/\+|"|'/g," ");
if ( ! value.trim() ){
continue;
}
value = value.toUpperCase();
alert( "Prior addition:" + this.get('length'));
// Prevent duplicates being added
if ( this.findBy('keyword',value) === undefined ) {
// Create the new Keyword model
var keyword = this.store.createRecord('keyword', {
value: value,
weighting: 1,
isNew: true
});
// Save the new model
keyword.save();
alert( "post addition:" + this.get('length') );
}
else {
alert( "Keyword [" + value + "] already defined");
}
}
// Clear the "New Keyword" text field
this.set('newKeyword', '');
}
I have a couple of alerts in there - one to display the array controller's length before I check for the value and subsequently createRecord on the store and one after. So I run this with 3 records, say 'tom','dick','harry' and if I add 'fred' to it, first alert is 3 and second alert is also 3 and fred appears.
I am confused as to why the 2nd alert is showing 3 and not 4 - I am assuming (perhaps incorrectly) that the arrayController has not yet been updated with the new record.
Secondly, if I restart then try adding fred,dick as an input, both get added, I would have thought fred should have been added and dick rejected as it was a duplicate.
Thanks in advance for any suggestions.
Jon
Judging by the way you wrote your code and that you use an 'ArrayController, I'm going to assume that the model for this particular route is all of your keywords. So themodel` hook is probably:
model: function() {
return this.get('store').findAll('keyword');
}
Assuming that, I think I can answer your questions.
First, the length doesn't change when you create the new record. It should increment from 3 to 4, but it doesn't. You are correct in assuming that the bindings haven't had time to update yet. You added the new record to the store, but the store hasn't had time to update the model for your controller yet because you still have control of the program flow. Most bindings are updated asynchronously in the run loop, so for many scenarios in Ember, you can't expect immediate updates.
Secondly, as for duplicates being added, it's hard to say but I think it's because you have a logic error.
// Prevent duplicates being added
if ( this.findBy('keyword',value) === undefined ) {
It seems to me as if you mistakenly put keyword instead of value. This might be just a typo when you were typing this question, but based on how you created your model, keyword is the type and value is the property.
Finally, a quick note: you shouldn't override the isNew property like you do when creating the new keyword. That will actually override the Ember-Data property with a permanent true value. (At least that's how I remember it working. I might be wrong, but it doesn't matter.) isNew is a computed property created by Ember-Data that will automatically update when the state of the object changes. Don't worry about setting it manually; just use the record as you normally would and Ember-Data will take care of the rest.

Using $watch to update data, ng-repeat not reflecting changes

I have a list of fooditems in $scope.raw and I want to show this data in columns so I'm changing the structure a bit. I do this in the sortStuff() function and store the updated data in $scope.allfood. There's a $watch that calls sortStuff() every time anything changes in $scope.raw (I'm using drag and drop to change the food category):
$scope.$watch('raw', function(){
$scope.allfood = $scope.sortStuff();
console.log($scope.allfood);
}, true);
This is what happens when food is dragged around:
receive:function(event, ui) {
var issueScope = angular.element(ui.item).scope();
scope.$apply(function() {
var recp = _.find(scope.raw, function(lineitem){
return lineitem.name === issueScope.receipe.name;
})
recp.cat = scope.col.name;
})
$(ui.item).remove(); // remove DOM
}
Basically, I search for the right object inside $scope.raw and change cat to new category for the food. I also delete the dom element because I'm counting on ng-repeat to refresh the view. This seems to work fine: console.log inside $watch shows that the object is being moved to the right category and the data looks what it should look like. However, visually, ng-repeat doesn't reflect the data.
Here's the jsfiddle.
Dragging an item from B to C works fine. Dragging one from A to B, makes two items from B disappear... the results are very inconsistent and I have no idea what is happening.
Any ideas what is going wrong? Or maybe any suggestions for a better way to do this?
The problem with your code is that the ng-repeat directive adds the property $$hashKey to every element in the list. This property is used by the directive to associate DOM elements with array elements.
Because you are passing the elements by reference, the ng-repeat directive writes the $$hashKey property directly into the objects of your $scope.raw array. A simple workaround is to copy the objects before inserting them into the $scope.allfood object.
_.each($scope.raw, function(recp){
recp = _.clone(recp);
switch(recp.cat){
...
}
});
Now the ng-repeat updates the objects of $scope.allfood, while the objects of $scope.raw remain untouched.
See the updated fiddle:
http://jsfiddle.net/b8Fa7/5/

How to get current rendered value in renderer in grid?

I want my renderer to run only once for each row.
So obviously my renderer should look something like
renderer: function() {
if (there_is_a_rendered_value_in_view) {
return rendered_value_in_view;
}
return 'generate some return';
}
Is it possible to do?
So how to get rendered_value_in_view?
UPD:
seems like I'm not detailed enough.
Well, the generated value after that is changed outside the grid, so the question is: How to get currently displayed value
You can always add boolean flag, and your rendered_value_in_view to the grid itself. And then in the renderer function check grid property and return it.
Update: from the Sencha docs here are list of parameters your renderer function will get:
value : Object
metaData : Object
record : Ext.data.Model
rowIndex : Number
colIndex : Number
store : Ext.data.Store
view : Ext.view.View
I think the last one will be your grid object.
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.column.Column-cfg-renderer
It'd be fairly difficult to try and capture the rendered value. I think the better way would be to add another model to your field that contains this new value. You can use a convert method so that when the original value changes, the display value can also change.
Maybe -
...
there_is_a_rendered_value_in_view:false,
renderer:function() {
if (!this.there_is_a_rendered_value_in_view) {
this.there_is_a_rendered_value_in_view=true;
return rendered_value_in_view;
}
return 'generate some return';
}

Categories