Get height of a element in ui-view - angularjs

I have a state that can have a variable height (depending on the content). I want to set that height as a css attribute for my background-color.
But I'm having trouble getting the correct height because the code fires before the content is loaded in the state.
I have this state,
$stateProvider
.state('home.suggestions', {
url: '',
views: {
"suggestions": {
templateUrl: '../assets/angular-app/templates/_suggestions.html',
controller: function(){
showHeight = $('.suggestions-container-wrapper').outerHeight();
console.log(showHeight)
}
},
},
})
But it always returns 175 (the height of the element before it loads the ng-repeat content.
How do I run the code after the all the calls are done?

Just found a simple solution. But a ng-init after the ng-repeat element, then it fires the function when it gets triggerd.
https://stackoverflow.com/a/24817862/848706
%div{"ng-init" => "setHeight()"}
Controller,
$scope.setHeight = function (){
$timeout(function(){
showHeight = $('.suggestions-container-wrapper').outerHeight();
console.log(showHeight)
}, 0);
}

Check out the docs on $viewContentLoaded. You might be able to do:
controller: function(){
$scope.$on('$viewContentLoaded', function(){
showHeight = $('.suggestions-container-wrapper').outerHeight();
console.log(showHeight)
});
}
Here is also another post that discusses it.

Related

angular array item not updating on scope change

Spent a few hours on this already, sifted through numerous stack posts and blogs but can't seem to get this to make my model update. More specifically, I am trying to update an array item (ng-repeat). In the simple case below, I iterate over venues list, and upon toggling a "like" button, I update the server appropriately, and reflect the change on the venues item on the $scope.
in my search.html I have a directive:
<ion-content>
<venues-list venues="venues"></venues-list>
</ion-content>
and search controller I have:
app.controller('bleh', function(Service) {
...
$scope.venues = [{ id: 1, name: 'Venue1', like: false },{ id: 2, name: 'Venue2', like: false }];
...
});
Nothing unusual there. Then in my venues-list directive:
app.directive('venues-list', function() {
function venueListController($scope, Service) {
$scope.likeToggle = function(venue, $index) {
Service.likeVenue(venue.id, !venue.like).then(function() {
$scope.venues[$index].like= !venue.like;
});
}
}
return {
strict: 'E',
templateUrl: 'venue.html',
controller: venueListController,
scope: {
venues: '='
}
}
});
then in my venue.html I have:
<div ng-repeat="venue in venues">
<p>{{venue.name}}</p>
<button ng-click="likeToggle(venue, $index)">Like</button>
</div>
I have tried many different options:
$scope.$apply() // after updating the $scope or updating scope within apply's callback function;
$scope.$digest()
$timeout(function() { // $scope.venues[$index] .... }, 0);
safe(s,f){(s.$$phase||s.$root.$$phase)?f():s.$apply(f);}
so
safe($scope, function() { $scope.venues[$index].like = !venue.like });
I haven't yet used the link within the directive, but my venues.html template is obviously a little more elaborate than presented here.
EDIT:
Just to keep the discussion relevant, perhaps I should have mentioned - the data is coming back from the server with no issues, I am handling errors and I am definitely hitting the portion of the code where the $scope is to be updated. NOTE: the above code is a small representation of the full app, but all the fundamental pieces are articulated above.
Search Controller
Venues Service
venue-list directive and venue.html template to accompany the directive
directive controller
EDIT #2
$scope.foo = function() {
$scope.venues[0].like = !$scope.venues[0].like;
}
Just to keep it even simpler, the above doesn't work - so really, the bottom line is my items within an array are not reflecting the updates ...
EDIT #3
$scope.foo = function() {
$scope.venues[0].like = !$scope.venues[0].like;
}
My apologies - just to re-iterate what I was trying to say above - the above is changing the scope, however, the changes are not being reflected on the view.
Perhaps the issue is with your service and promise resolution.. Can you put a console.log there and see if the promise resolution is working fine? or Can you share that code bit. Also where are you checking for scope update? within directive or outside
OK after some refactoring I finally got it working.
The "fix" (if you want to call it that) to my specific problem was:
instead of passing an array of venues, I was iterating over the array on the parent controller, passing in a venue as an element attribute that would bind (two-way) on the isolated scope of the directive.
so, instead of:
<ion-content>
<venues-list venues="venues"></venues-list>
</ion-content>
I now have:
<ion-content>
<venues-list ng-repeat="venue in venues" venue="venue"></venues-list>
</ion-content>
and my directive now looks like:
app.directive('venues-list', function() {
function venueController($scope, Service) {
$scope.likeToggle = function(venue) {
Service.likeVenue(venue.id, !venue.like).then(function() {
$scope.venue.like = !venue.like;
});
}
}
return {
strict: 'E',
templateUrl: 'venue.html',
controller: venueController,
scope: {
venue: '='
}
}
});
This did the trick!

Use same controller and view for search and non-search in Angular

I am working on an angular application. I have one controller and one view. I would like to use the same view with and without a search field. That means if the user needs to see the search view or the regular view with the data already populated, then I would like to do this with the same controller and view. My thought that was that I could maybe pass an additional parameter from the app.js to decide in the controller if the search field needs to be displayed or not. Is that possible?
I found the solution set the params property to an object:
In the app.js:
.state('inventorySearchReport', {
url: "/inventoryReport",
templateUrl: "templates/reports/inventoryReport.html",
controller: "inventoryReportCtrl",
cache: false,
params: {
search: { value: true }
}
})
.state('inventoryReport', {
url: "/inventoryReport",
templateUrl: "templates/reports/inventoryReport.html",
controller: "inventoryReportCtrl",
cache: false,
params: {
search: { value: false }
}
})
In your controller inject $state and use as:
$scope.enableSearch = $state.params.search
You can use ng-if Angular documentation for ng-if
First initialize a variable say
$scope.test= false; in your controller
suppose you want to display the search field when your data is populated through $http then in that you change
{
$scope.test = true;
$http({..})
}
and in your view
<input type="text" name="search" ng-if="test==true"/> // will display the search when data is populated

AngularJS two way data binding in directive not working

I have a directive that updates a bound property, but it never seems to update the original property!
directives.directive('recordVideo', [function () {
return {
scope: {
showRecordVideo: '='
},
controller: "recordVideoController as ctrl",
templateUrl: '/views/recordvideo.html'
};
}]);
<record-video data-show-record-video="showAddScheduleDialog"></record-video>
When I set $scope.showAddScheduleDialog = true in the parent controller, the directive sees the change and shows the dialog. When the dialog itself sets its property $scope.showRecordVideo = false the bound property on the parent controller showAddScheduleDialog never updates!
Why is this?
I have tried putting $scope.$watch on both the parent controller and the directive. The changes only propogate down to the directive and never back up to the controller!
The problem is caused by javascript prototype inheritance (the long answer). The usual hack is to change a property inside:
This stays the same:
scope: {
showRecordVideo: '='
},
In controller:
$scope.showRecordVideo = {
state: true
};
In modal:
$scope.showRecordVideo.state = false;

How to Check for unsaved changes when switching nested views in a same Page?

When we are switch between one state to another state here i am able to check unsaved changes and i can ask user for conformation before moving one page to another but in a same view i have multiple forms in that if am switch between one form to another form first i have to to give message to the user are you sure u want leave page without saving the data then only i can move to another form How can i do this.
example of multiple forms in same view below i have metioned
<div ng-switch-when="formTab">
<div ng-include="'/views/tmpl/workForm.html'"></div>
</div>
<div ng-switch-when="effortTab">
<div ng-include="'/views/tmpl/workEffort.html'"></div>
</div>
In the above example while moving from formTab to effortTab i need to show that unsaved changes message
Use the $dirty property of the form:
console.log(myForm.$dirty);
Plunker
I got solution for this Instead of using ng-switch we can use nested states with the parent state.
using unsavedChanges directive we can check automatically whether any unsaved data is there in the current form. if condition matches this directive will warn the user this will work based on ui-state so it will check automatically when we are injected directive no need to do manually..
Below example
$stateProvider.state('edit', {
abstract: true,
url: '/edit',
templateUrl: 'edit.html',
controller: function($scope) {
$scope.model = {};
$scope.validator = {
basic: null,
extended: null,
isValid: function() {
return this.basic && this.extended;
}
};
}}).
state('edit.formTab', {
url: '/formTab',
templateUrl: 'formTab.html',
controller: function($scope) {
$scope.$watch('formTab.$valid', function(value) {
$scope.validator.formTab= value;
});
}}).
state('edit.effortTab', {
url: '/effortTab',
templateUrl: 'effortTab.html',
controller: function($scope) {
$scope.$watch('effortTab.$valid', function(value) {
$scope.validator.effortTab= value;
});
}});
we can use below link :
http://plnkr.co/edit/OyVBpp?p=preview

Changing ui-view value programmatically not updating the view itself

I am using AngularJS and UI-Router and have a list of links which I want to change the view below based on which one is clicked.
Right now on click the value itself changes perfectly, but the view does not change on click.
Here is the state definition
.state('home.person', {
cache: false,
url: '/person',
params: {
personIndex: null,
personID: null
},
views: {
'mainContent#home.person': {
templateUrl: 'app/person/person.html',
controller: 'personController'
},
'interviewForm#home.person': {
template: "interviewform!"
},
'employmentDetails#home.person': {
template: "employmentDetails!"
},
'skills#home.person': {
template: "skills!"
}
}
})
The HTML
<div class="sub-tabs">
<ul>
<li>Interview Form</li>
<li>Employment Details</li>
<li>Skills</li>
</ul>
</div>
<pre>{{currentSubTab()}}#home.person</pre>
<div ui-view="{{currentSubTab()}}#home.person"></div>
I put the pre in there just so I can monitor the values change easily
And the controller to set/get the current subtab
var _currentSubTab = "interviewForm"; // Default
$scope.setSubTab = function (val) {
_currentSubTab = val;
};
$scope.currentSubTab = function () {
return _currentSubTab;
};
It correctly defaults to and shows interviewForm. If I click Employment Details link the value indeed changes but the view itself does not update! If I change the default value to employmentDetails then it does correctly show that view, but again clicking does not change.
I've tried adding cache: false but that didn't fix it
I've tried wrapping the return in a $scope.$apply but I get digest errors
I've tried using getter/setter functions as you see here, or just using a straight up $scope value and setting it directly in the ng-click but that also didn't work
1) How can I programmatically update a child ui-view?
Update
As Jase suggested below, I know that I can do this by breaking all of these out into their own states. I want to accomplish this feature instead without changing states to update the subtab view.

Resources