Variable showing as undefined - angularjs

I am having trouble with passing the results of checkboxes from my view to the controller and just get "undefined" in the console log.
FYI - I have my controller as "camp".
In my view I have the following:
<div style="padding:20px;">
<h5>Add a Business</h5>
<md-content style="padding:20px;">
<md-checkbox
ng-repeat="business in camp.businesses"
ng-model="business.selected"
aria-label="Checkbox"
>
{{business.business_name}}
</md-checkbox>
</md-content>
<md-button class="md-raised" ng-click="camp.addBusinesses(business)">
<i class="fa fa-plus"></i> Add
</md-button>
</div>
In my controller I have the following function in an "angular.extend()"
addBusinesses: function(val){
console.log('Display Results: ', val);
}
If I just use the function to log the click event, it's fine. But when I try to pass the "business" object, it says "undefined".
What am I missing here???

The issue is your <md-button> is outside the ng-repeat. Your ng-repeat ends with the </md-checkbox> so when it gets to the button, business is indeed undefined.
Try reformatting your code so that the button is still within the scope of the ng-repeat. Maybe you want the repeat on the md-content instead? I'm not sure what the page is supposed to look like so I can't advise more than that.

Related

changing md-selected with md-tabs and using md-button (prev, next)

I am experiencing a strange behavior when switching tabs using different methods of changing the tab index. I can change md-selected using the $scope.changeQuestion function with ng-click. I can also use the built in clicking of the md-tab to change md-selected. The issue lies when I click the md-tab and then try to click my prev or next buttons that utilize the $scope.changeQuestion function. If I click the tabs and then try to use my buttons to change the index, the buttons don't change the tab index anymore. They do log the appropriate index I want to switch to, however.
controller
$scope.changeQuestion = function(index){
$scope.selectedQuestion = index;
};
html
<md-tabs md-selected='selectedQuestion' md-stretch-tabs md-dynamic-height md-border-bottom>
<md-tab ng-repeat='question in assessment.questions | toArrayKeepKeys | orderBy: "order"'>
<md-tab-label>
{{question.order}} <i class="fas fa-fire fire" ng-if='question.bonus'></i>
</md-tab-label>
<md-tab-body>
<div class='question-tab-content'>
<question class='margin-top-1em' details='question' answer='answers[question.key]'></question>
<div>
<md-button ng-click='changeQuestion($index - 1)' ng-hide='question.order === 1' class='md-primary md-raised no-left-margin'>Previous</md-button>
<md-button ng-click='changeQuestion($index + 1)' ng-hide='question.order === _.size(assessment.questions)' class='md-primary md-raised no-left-margin'>Next</md-button>
</div>
</div>
</md-tab-body>
</md-tab>
</md-tabs>
Here is the example of the behavior:
I was able to get a working example in codepen but can't seem to get it to work in my project.
Update
Tried putting a $watch on $scope.selectedQuestion and it doesn't fire if I click the tabs. It's like the md-selected='selectedQuestion' and $scope.selectedQuestion are different but only after I click a tab.
Found Solution: scope inheritance
Changing $scope.selectedQuestion = 0; to $scope.selectedQuestion = { selected: 0 }; and updating other references did the trick.
Unexplained: why the codepen example works without the modifications from the solution

AngulaJs: ng-click not work on netsted uib-accordion

I use nested uib-accordion, and I want add ng-click to each of uib-accordion.
<uib-accordion close-others="oneAtATime1">
<div uib-accordion-group class="panel-default" is-open="prInfo.isOpen" heading="{{prInfo.name}}"
ng-click="getPayrolls(prInfo)"
ng-repeat="prInfo in allPersonInfoNames">
<uib-accordion close-others="oneAtATime2">
<div uib-accordion-group class="panel-default" heading="{{payroll.logPeriod.name}}"
ng-click="getPayroll(payroll)"
ng-repeat="payroll in prInfo.payrolls | orderBy: 'logPeriod.dbId': reverse = true">
<div class="row">
<div class="col-md-4">
<h1>in nested accordion</h1>
</div>
</div>
</div>
</uib-accordion>
</div>
</uib-accordion>
So, when I click on first accordion, first ng-click work correctly, but when I click on second accordion, again first ng-click is called, and second ng-click never called.
I can solve this problem by adding second ng-click in body of accordion,
but by this solution, I have to click 3 times to work second ng-click, first time for open the first accordion and run first ng-click, second time to open second accordion and third time click on function in nested accordion body to run second ng-click. How can I separate ng-click functions by first solution?
demo on plunker
The problem your facing seems to be related to this thread: AngularJS ng-click stopPropagation
When you click on the second ng-click, you have to stop the event propagation to prevent the first method to be triggered.
I Hope it may help

Using ng-init with async operations

Is it possible to use ng-init that make an async call whilst inside an ng-repeat?
For example consider the following:
<div ng-repeat="order in orders">
<md-list>
<md-list-item>
{{order.id}}
</md-list-item>
<md-list-item ng-init="detail = getOrderDetail(order.id)">
{{detail.itemName}}
</md-list-item>
</md-list
</div>
I'd like to call a function for each item being repeated over which will go and fetch some extra data over http.
So in my getOrderDetail I have something this kind of thing:
function getOrderDetail(id) {
return myService.getOrderDetails(id).then(function(orderDetail){
return orderDetail;
});
}
This doesnt work for me, as the detail.itemName in my second md-list-item does not resolve to anything, but I can see the network request made and if I add a breakpoint in my function call I do see the order detail returned with the itemName property present.
Is there a limitation when using ng-init that prevents it working\re-evaluating for async operations?
Thanks
There I can see couple of things wrong implemented
Another wrong thing is you shouldn't be using ng-init for this case
This is not how you can make it working, like you are considering that, data returned from promise will directly put inside a variable.
I'd make those call when I get data & will put data in order object of that element so that I can grab details later from that particular order only
angular.forEach(orders, function(order){
getOrderDetail(id).then(function(response){
order.detail = response;
})
});
HTML
<div ng-repeat="order in orders">
<md-list>
<md-list-item>
{{order.id}}
</md-list-item>
<md-list-item>
{{order.detail.itemName}}
</md-list-item>
</md-list>
</div>

md-menu md-list-item Angular Material

I want to have a md-menu on a md-2-line list-item directive. note: NOT on the secondary action but primarily on the list item itself. The documentation states that the first element is used as trigger and is left in the DOM, while the second represents the menu contents. So I was surprised that the following structure does not work.
<md-list>
<md-menu>
<md-list-item class="md-2-line" ng-click="openMenu($mdOpenMenu, $event)" ng-repeat="prop in properties">
<div class="md-list-item-text">
<h3>{{ prop['display_name'] }}</h3>
<p>{{ object[prop.key] }}</p>
</div>
</md-list-item>
<md-menu-content width="6">
<md-menu-item ng-repeat="val in prop['values']">
<md-button ng-click="updateAttribute(prop.key, val)">
{{val}}
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</md-list>
However, I don't really see what I am doing wrong. I also keep getting the following errors, of which I do not know the meaning:
angular.js:13550 TypeError: Cannot read property 'hasAttribute' of undefined
at r (http://localhost/flatt.io/app/node_modules/angular-material/angular-material.min.js:13:26527)
and
angular.js:13550 TypeError: Cannot read property '0' of undefined
at enableHoverListener (angular-material.min.js:13)
Regards
Your ng-repeat where prop is defined is on the md-list-item tag. prop falls out of scope when that tag is closed, so it's not available when you go to define your md-menu-content.

Show an html element dynamically within a ng-repeat section using angularjs

I have a ng-repeat directive being used in html code as below. I would like the following html: '{{command.Title}}', to be only added if the command.Title was not an empty string. In other words I do not want divs to appear as empty divs when command.Title is an empty string.
Question: Is this possible and if yes, then how can it be done?
<md-list class="control-panel-list">
<md-item ng-repeat="command in controlPanel.commands">
<div>{{command.Title}}</div>
<md-button aria-label="{{command.text}}" class="control-button"
ng-click="controlPanel.onCommandButtonClick($index)">
<i class="{{command.iconCss}}"></i>
<span class="reports-control-button-text">{{command.text}}</span>
</md-button>
</md-item>
</md-list>
If you don't want the div as part of the DOM at all, try using ng-if instead of ng-show/ng-hide...
<div ng-if="command.Title">{{command.Title}}</div>
Simply use ng-show to hide the element if empty:
<div ng-show="command.Title">{{command.Title}}</div>

Resources