using `angular.copy ` to set model - what's the benefit? - javascript

Today I was reviewing this widget and found the following way to set property:
if (selected !== $scope.dropdownModel) {
angular.copy(selected, $scope.dropdownModel);
}
I'm wondering what's the benefit of such method as opposed to:
$scope.dropdownModel = selected;

Sometime you want to have a copy of the original model lying around so that you can reset the element's model to the original value, for example, if you have a form and the user edits it, then decides to cancel the changes, how would you revert the forms input value to the original ones? You need a copy of the original model since the binding between the model and the form is 2 way, and all changes made to the form will affect the model, so you need a copy of the original model if you want to roll back the edit. Angular.copy basically removes the reference from the object and creates a separate copy.

Related

How to avoid reflection of data entered in popup to the table before it is saved using Angular2

I have an edit popup, when the popup opens and i edit, it is reflecting on the table. I must avoid the reflection, once i click on save button then only the edited part must be displayed on the table. I am able to do this only for one input, i am not getting how to carry out the same way for other 2 inputs.
//Ts
editTutorial(tutorial) {
this.editTutorials.show();
this.edit_tut = tutorial;
}
You are assigning tutorial value which you sent from table into edit_tut varable, which is working as two-way binding.
so, the data in the table is getting changed along with your input.
The solution can be changing the variable reference, you can do something like,
editTutorial(tutorial) {
this.editTutorials.show();
let tut = JSON.parse(JSON.stringify(tutorial))
this.edit_tut = tut;
}
This will change the value reference and will work for you.
You have to have two different properties on your component, referencing to two different object instances. Few things to do:
Step 1: on clicking "edit", make a copy of the table row (all props) and put them inot the modal. Keep the reference to, e.g. table row you're editing, or _id or something.
In your case, add a property to TutorialComponent called currentlyEditing: any. Then, modify your editTutorial method:
editTutorial(tutorial) {
this.editTutorials.show();
this.currentlyEditting = tutorial;
}
Step 2: editing those should not reflect on the table. Go on and edit your thing.
Step 3: upon saving, sync your changes back to the table, or rather, to the original data set that's being displayed in the table. That's why you needed the reference from step 1.
Now, it's not clear to me if your edit_tut component is the one that saves changes. But if it is, I think everything will work as is. If not, you'd have to, after saving and response of "success", go and find the original tutorial in the tutorials array, and replace it with the edited component.

binding updates in knockout.js

This may well be a very basic problem for anyone familiar with knockout.js, however it is causing me a problem.
I have a situation where I have a model containing an array of items that is dynamically added to and displayed in the view.
So far no problem, I can add entries into the model and the view is updated appropriately.
However. each item in the array itself has an array as a property, this is an array of object, and when I update the properties on these objects the view is not updated.
It is difficult to demonstrate this is a short code snippet so I have created a JsFiddle to show the problem:
https://jsfiddle.net/mikewardle/t0nvwqvL/1/
I have tries making the properties generated by calling
ko.observable()
rather than initializing them directly, but to no avail.
clicking the add button adds items to the array on the model itself.
either of the change... buttons alters the properties of the objects in the inner array.
As Ko2r stated your properties are not declared as observables and therefore updates will not be noticed by knockout.
To fix your changecolors() function you just need to change your linePusher function to create the color as an observable:
var linePusher = function (color, name) {
self.lines.push({ color: ko.observable(color), name: name, current:0 });
};
and then update usages of the color property to box/unbox the observable instead of replacing its value with the standard assignment operator, "="
for (i=0;i<counters.length;i++){
var lines = counters[i].lines();
for (j=0;j<lines.length;j++){
//lines[j].color = color;
lines[j].color(color); //sets the existing observable to the new value
}
}
Unfortunately I can't seem to make sense of your code enough to figure out what the increment() function is supposed to be doing so I can't tell you how to fix it, but hopefully the fixes to changecolors() put you on the right track.
You might want to read up on working with observables

Struggling for Backbone syntax in collection events

I have a collection, I can do this successfully ('this' is the collection instance):
this.on('change:username', function(model,property,something){
// model is backbone model that changed
// property is the property that changed (username in this case)
// something is some empty mystery object that I can't identify
}
however what I want to do is this:
this.on('change', function(model,property,something){
// model is backbone model that changed
// ***how can I read the properties that changed here?***
// something is some empty mystery object that I can't identify
}
the problem is that in the second case, I can't get the property that changed...maybe that's because it's potentially multiple property changes all at once.
How can I capture that properties that changed in the second case? is this possible?
The only way I know how to do this would be
this.on('change', function(model, something){
// something object is unidentifiable
var changed = model.changed; //hash of changed attributes
}
so my other question is: what is that mystery object "something"? It is just an empty object...?
You have a couple of options you can use in general change events:
Backbone.Model#hasChanged: This will allow you to see if a model attribute has changed in the context of this change event. If so, you can get its new value and apply it to the view (or whatever other context) as needed.
Backbone.Model#changedAttributes: This will allow you to get all changed attributes since the last set() call. When called with no parameters, it is a defensively cloned copy of the changed hash; you can also pass in a hash of parameters and get only what is different about the model relative to that set of key/value pairs.
Backbone.Model#previous: This will allow you to get the previous value of a model attribute during a change event.
Backbone.Model#previousAttributes: This will allow you to get all the previous values of a model during a change event. You could use this to completely undo a change (by calling set with the result of this function) if you wanted to.
By the way, the third parameter of the change:attr event (and the second of change) is an options object, which can be useful if you want to specify custom values that can be read by your event handlers. There are also a number of standard options Backbone will handle specially. See the documentation for Backbone.Model#set for more information on the specific options, and take a look at the Backbone event list to see the callback signatures expected when those events are triggered.

bind complex json object to knockout dropdown menu

I have a complex object being bound to a drop down. See the jsfiddle.
Is this the correct way to bind to a complex object for a drop down menu.
The drop down must bind to an initial value(currently working)
Changing the selected index in the drop down needs to update the knockout object. This is sort of working. The object is updated when save is called so the drop down's object value is being passed to the Format object. -- However.. This value is not updated in the UI.
I am not sure if it is the mapping that needs some work to make format into an observable. The value of SelectedFormat never seems to change from the first load.
any help on getting this to update the ui and text output of the object would be appreciated.
Edited: question to give requirements more clarity
code on js fiddle
1) No its easier than that, just use optionsText point out the member like
optionsText: 'Name'
Object reference is already implicit the optionsValue so you can skip that, if you want to explicit set it anway you can do the same there and just point to the member optionsValue: $data but its not needed. In other words, this would do http://jsfiddle.net/QrvJN/7/
2) The value and options binding are matched on object reference so if initial value and the list of options do not share references you need to match them yourself. You are doing it a little strange though, I did a binding for this that takes care of the problem http://jsfiddle.net/ewSU2/
3) THis is not needed if you check my solution 2)

valueBinding to content of array

I have this controller with a value.
App.xcontroller = SC.ArrayController.create({
...some code...
array_values = [],
..more code...
})
Now i have somewhere in a view this valueBinding
valueBinding: 'App.xController.array_values',
When I change values in the array the view does not get updated. but when i do
the following in the controller:
var array_values = this.get('array_values');
... adding / removing values to the array....
if (x_values.contains(x)){
x_values.removeObject(x)
} else {
x_values.pushObject(x);
};
this.set('array_values', array_values.copy());
the binding works, the view gets updated. But ONLY with the copy().
I don't want to make a copy of the array, IMHO this is not efficient. I just want to
let the valueBinding know content has changed..
the x values are just a bunch of integers.
The reason i want this: I want to change the value key of a SegmentedItemView. I want to change the active buttons. But I do not know on forehand how many segmentedviews I have
so I thought i bind the value of every generated segemented view to some common array and change that common array to be able to change the active buttons on all of the segmented views. Since each button represents an item with an unique key it works fine. except that i have to copy the array each time.
set the content property of the xcontroller
Bind to the arrangedObjects property of the xcontroller
You need to use KVO compliant methods on the array to get the bindings to fire. The ArrayController itself has an addObject and removeObject methods. Arrays in SC have been augmented with a pushObject method (among others), which is also KVO compliant. So if you use the KVO methods the view should update.
The reason your view does not update is because you are bound to the array, but the array itself did not change. When you do a copy, the array itself changes, so the bindings fire.
You might also want to try
this.notifyPropertyChange('x_values');
in the controller after you make the changes, but that is less preferable to using the built in KVO functionality.

Categories

Resources