Angularjs grid selectedItems always returning undefined? - javascript

Any reason the angularjs grid in my sample won't show the selectedItems properly? That is, any time I try to reference the selectedItems I get "undefined." I've tried in Chrome and IE with the same result.
I've made a plnkr that is the "basic" example on the angular grid page with a bit of extra javascript to try and show the selected items.
The plnkr: http://plnkr.co/edit/wPnMGQOzKSOTdeaAjoB8?p=preview
The relevent code:
$scope.gridOptions = {
data: 'myData',
selectedItems: $scope.mySelections,
afterSelectionChange: function (row, event) {
if (row.selected) {
alert('Items selected ' + $scope.mySelections);
alert('Items selected ' + $scope.gridOptions.selectedItems)
}
}
};
I get "undefined" when trying to evaluate the selected items, either with $scope.mySelections or via the grid directly. I've put a "debugger;" line in "if" and checked the values - there doesn't appear to be a selectedItems property on the grid?
(edit: removed the ** from the code block. Forgot you can't boldface code here)

You forgot to initialize your $scope.mySelections property. Because of this, every time you'd print its value, you would get undefined.
Check a fixed plnkr.
Of course, it alerts a [Object object] for each, but this is a matter of how you want to print your objects.
If you want to alert your objects in a more sensible way, you could do something like this plnkr.

Related

JavaScript problem converting strings inside object (inside loop)

While building a carousel module for Joomla I am having 2 JavaScript issues I can't get fixed. I've been trying for 2 days. Hopefully someone here can point out what I am doing wrong.
I can't get a boolean from a string "0" or string "1"
And I can't JSON.parse() to convert an object string to a JavaScript object
The situation:
To be able to have multiple instances on 1 page I am passing each modules individual settings (via php) to 1 object in my javascript file. Each module is 1 key value pair inside the object, the value being its own settings object. Basicly, this is how the JS recieves it:
const moduleSettings = {
"103":{"items":3,"margin":5,"loop":"1","center":"0","responsive":"{0:{items:1}}"},
"105":{"items":3,"margin":5,"loop":"0","center":"1","responsive":"{0:{items:2}}"}
};
Next I need to loop over each module to initialize the settings. This is done on ready using jQuery.
jQuery(document).ready(function() {
// Loop over each module
const modules = Object.keys(moduleSettings);
for (const id of modules) {
const target = "carousel-" + id;
const params = moduleSettings[id];
// Callback to evaluate true/false params
function eval(singleParam) {
return params[singleParam] === "1";
};
// Initialize carousel
jQuery(target).owlCarousel({
items: params.items,
margin: params.margin,
loop: eval("loop"),
center: eval("center"),
responsive: JSON.parse(params.responsive)
});
};
});
The carousel properties items & margin are numbers. No problem there, but these are recieved as numbers from the start.
The problem:
The properties loop & center should return a boolean, based on the callback function eval(). But they just return the string "0" or "1".
The property responsive should return an object. But this still remains a string object "{...}".
The console error:
The first problem above does not block functionallity. It works, but I want to understand why my values are not booleans.
The second problem however causes console error and make the carousel not work. This is only IF responsive is not an empty string. When responsive is an empty string, it works. But I need the responsive setting.
I've been looking for the cause of this issue for 2 days now. It's getting frustrating. Any pointers would be most helpfull. Thanks!
instead of using eval function use can you below
jQuery(target).owlCarousel({
items: params.items,
margin: params.margin,
loop: !!params.loop,
center: !!params.center,
responsive: JSON.parse(params.responsive)
});
For the second issue, you need to change the structure from your server side code to generate this module settings JSON. The responsive object is not a proper JSON. its should be like
responsive: {items:1} or responsive: [{items:1}]
If you can post that code then I can tell you the change need to made there.
In the example you've provided, you're not evaluating the params field by name provided as a singleParam argument, but the actual params.singleParam field, which is undefined. To fetch field by it's name use brackets syntax: params[singleParam].

Javascript: JSON key values not updating on request

I'd like to update my JSON value based on selection.
So for that I have simply update my json value as data.childShow = true.
Now as per the screenshot on line no 78 it's actual value is false and after updating it's value to true ( ref line no 84 ) and it shows as value updated on line no 85 but when i expand that console object it shows as false.
So, why the values are differing when open the object on console log ?
Screenshot while not opening object of line no 85
P.S: Before raising this question I have already tried this demo, but it is not working in my actual application so that i raised this question.
Try this thing in console it might solve your confusion. Add an object like let data = { childShow: false }. Then log it in console. Do not expand right now. Now change the value of data.x = true; in expanded value but it also has childShow=false in first line. Now expand console log value. You can see it is displaying childShow = true. So it might be fetching current values when we expand.
You can also log childShow and check what exactly values hold by data.childShow. Like in below snippet. It will show you when you do console.log(data.childShow); first time it will show false and second time it will show true which is as expected.
Try with below like. 1. Open console of browser. 2. Click on Run Code Snippet. 3. Expand object in console.
const data = {
childShow: false,
}
console.log(data);
console.log(data.childShow); // Output false
data.childShow = true;
console.log(data);
console.log(data.childShow); // Output true

AngularJS - filter logic from controller works, not being displayed correctly

I am trying to use a filter that I have written in my controller to narrow down a select list using ng-options. The filter logic is working, but the results aren't getting displayed.
Here's the relevant part of my controller:
$scope.ESGFilter = function() {
var esg;
var filteredESGs = [];
// LOGIC GOES HERE TO POPULATE THE filteredESGs ARRAY
console.log(filteredESGs);
return filteredESGs;
}]);
Here's the HTML:
<select class="input-block-level" id="inputESG" name="inputStoch"
ng-model="Run.ESG"
ng-options="econ.Id as econ.Name for econ in econData | filter:ESGFilter" size="5">
</select>
I suspect the issue has to be with "filter:ESGFilter" in the HTML... I can't figure out why the array that I return from the function isn't being displayed. The function in the controller is definitely being called and the logic is working.
For reference, the console.log outputs: [Object, Object] -- when I expand the properties of these objects, I confirm that they are the ones that I want. The select list, however, displays all four objects (I'm filtering down from an array of four).
Your filter needs to return a true/false statement. Write your filter like this:
$scope.ESGFilter = function(item) {
// if you want to keep the item return true, else false
};
This works because the ngOptions takes each item in your array and passes it to your filter function. Your example is not working because it's returning an empty array which will always resolve to a truthy value, and all objects will be accepted and not filtered.
Here's a plunk:
http://plnkr.co/edit/RfKMcXDKy1m1EGyoEpS7?p=preview

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