I'm working on ionic+angularjs,
SITUATION
I have a list of items, each item redirects to a new page(form). after filling up the form and goes back to the list, the item will be indicated with a checkmark.
from the form, in order to go back to the list i used $ionicHistory.goBack()
QUESTION
how can i rerun a controller from the list of items, below is the code i used:
HTML:
<ion-nav-view>
<ion-content>
<div ng-controller="MyCtrl">
</div>
</ion-content>
</ion-nav-view>
JS:
.controller('MyCtrl', function($scope) {
console.log('View is shown');
})
Ionic emits events from the view's scope like $ionicView.enter, $ionicView.beforeEnter which could be helpful for you to re-run your controller logic when the user enters the view.
Documentation
Related
Basically I want to achieve like this scenario:
https://i.stack.imgur.com/LLTcK.png
My research led me to $compile, $trustAsHtml,at last directive.
In $compile and $trustAsHtml I can only append static template or only html but can't use dynamic things such ui-sref, ng-click etc.
So, I tried to create directive it is not working and also I am unable to add multiple template on click.
controller :
app.controller('Ctrl', ['$rootScope', '$scope',function ($rootScope, $scope)
{
$rootScope.enableDirective=false;
if(userHasOneApp){// checking some at least one app then only do action
$rootScope.appicon="img_url"; // data which i am passing
$rootScope.appname="App_name"; // data which i am passing
$rootScope.enableDirective=true;
}
}]);
custom directive:
app.directive('headerTemplate', function () {
return {
template:'<a ui-sref="/event" ng-click="editIt()">'
+'<img src="{{appicon}}"></a>'
+'<span>{{appname}}</span>',
scope:{
appname:'=',
appicon:'='
}
};
});
Header view :
<div> class="headerdiv">
<ul ng-if="enableDirective">
<li header-template appicon="appicon">
</li>
</ul>
</div>
Main view :
<div> class="maindiv">
<ui-view></ui-view> <!--basically I want to append template here -->
<button>Add next template</button>
</div>
Where I am doing wrong ?
Well i was facing the same issue
Check out the following link
This will surely help you.
I have implemented this and it worked in my scenario where i wanted to serve a directive when required i.e Lazy Loading of directive
https://www.codeproject.com/Articles/838402/Lazy-loading-directives-in-AngularJS-the-easy-way
I try to declare a global list in my ionic project with rootScope variable. My aim is to update this list with specific messages. According to my scenario, I have different views with their forms. I try to hold completed actions in another view in the application. When I press the button of "x" form, "x form is completed" message should be pushed into that global list. After that, when I press the button of "y" form, "y form is completed" message should be appended to that list. Then, I display the content of global list in the completed action view.
In each view, I have a button as shown in screenshot2.
Also, I connected those views with a controller in the controller.js file below:
I created a global list using rootScope for other controllers to reach that list values
.controller('MainCtrl', function($scope, $rootScope, $state) {
$rootScope.onButtonClick = function (obj) {
$rootScope.buttons = [];
$rootScope.buttons.push(obj);
$state.go('app.completed');
}
})
Then I connected Completed Actions view with another controller to display the final view of the list to see all pressed buttons in the application:
.controller('CompletedCtrl', function($scope,$rootScope,$state) {
$scope.buttons = $rootScope.buttons;
$scope.onCompletedButtonClick = function(){
$state.go('app.homepage');
}
})
Completed Actions view (html file):
<span style="color:white">COMPLETED TravelBuddy</span>
</ion-nav-title>
<ion-content>
<div class="list">
<ion-list>
<ion-item ng-repeat="item in buttons">
{{item}}!
</ion-item>
</ion-list>
<label class="item">
<button class="button button-block button-balanced" ng-click="onCompletedButtonClick()">+</button>
</label>
</div>
</ion-content>
After I run my mobile application, I can not display all pushed items from the list, I only see the first pressed button message in the completed actions in screenshot1. How could I solve this problem?screenshot1screenshot2
You wrote "message should be appended to that list."
but you clean it each time a button is clicked.
move this line out of onButtonClick: rootScope.buttons = [];
Working plunker https://plnkr.co/edit/Y2cJrUGYcygvM9i6wKx5?p=preview
<ion-item ng-repeat="item in buttons track by $index">
{{item}}!
</ion-item>
If you want to push duplicates track by $index should be there. Otherwise, you will unable to push, an error will be thrown
Working code
$rootScope.buttons = [];
$rootScope.onButtonClick = function (obj) {
$rootScope.buttons.push(obj);
$state.go('app.completed');
}
The list will definitely update but if you didn't use ng-repeat="item in buttons track by $index", The above code will throw an error if you push dupes. So, add track by $index to get the desired result
I have searched through a lot of questions regarding $route.reload() and I think I still have a fundamental misunderstanding of how it and Angular are actually working. I really want to understand what is actually going on (not just a quick fix) so I apologize if this question gets rather verbose.
I am trying to create an app that will allow the user to input information into a form and then use ng-view and a controller LivePreviewController to display that form data in a "live preview" of the form which has some unique styling and other information associated with the form that the user does not input themselves.
This is very simple to do if the "live preview" is occurring on the same page as the user is inputting information using something like this
<input type="text" ng-model="form_name" />
<div ng-bind="form_name"></div>
What I would like to do is something like this.
<!--Location is: localhost:8888/form_page.html -->
<input type="text" ng-model="form_name" />
<!-- ng view is displaying the partial view: styled_form.html -->
<div ng-view></div>
Then I have another page styled_form.html which is the partial view that gets displayed by the ng-view div.
<!-- partial view page is styled_form.html -->
<div ng-bind="form_name"></div>
Both of these pages are controlled by the same controller LivePreviewController.
There are a lot of things I imagine that I am probably doing incorrectly. First thing could be the routing. I had some issues with the routing as app is only used on one page of a multi-page website my routes are setup as follows.
var previewApp = angular.module('previewApp', ['ngRoute']);
previewApp.config(['$routeProvider', function($routeProvider){
$routeProvider
.otherwise({
redirectTo:'/styled_view.html',
controller: 'LivePreviewController'
});
}]);
//Controller Code
previewApp.controller('LivePreviewController', [$scope, $route, function($scope, $route){
$scope.form_name = 'temporary name';
}]);
All of this works as expected when the form_page.html is originally loaded, but when the user changes the name in the text input the ng-view displaying my styled_form.html page is not changed. This also makes sense because the styled_form.html needs to be reloaded with the new information.
Here is where the noob starts. My first inclination was to create a refresh button and add a function in my LivePreviewController to refresh the page using $route.reload()
previewApp.controller('LivePreviewController', [$scope, $route, function($scope, $route){
$scope.form_name = 'temporary name';
$scope.refreshPage = function() {
$route.reload();
console.log($scope.form_name) //to ensure scope is updating
};
}]);
And then updated my html to include the button as follows
<!--Location is: localhost:8888/form_page.html -->
<input type="text" ng-model="form_name" />
<button ng-click="refreshPage()"> Update the Page </button>
<!-- ng view is displaying the partial view: styled_form.html -->
<div ng-view></div>
The function is working just fine when the button is clicked and the updated scope variable is displaying in the console, but my live preview is not updating. After looking through the Angular documentation I have a hunch as to what is happening. It states...
Causes $route service to reload the current route even if $location hasn't changed.
As a result of that, ngView creates new scope and re-instantiates the controller.
So if I understand the docs correctly, which I obviously don't, what is actually happening on $route.reload() is that when styled_form.html is getting reloaded the updated $scope.form_name is getting wiped out and the original $scope value is getting shown on the page. So...
Question 1: am I understanding this correctly i.e. is $route.reload() wiping out my $scope and reloading the old $scope variable, or is my $route.reload() just not reloading the page at all?
Now if I am interpreting my issue correctly my guess (seen suggested on here in other topics) is that the solution would be to create some type of service to store my data and then call that service inside of the controller. This workflow would look like
User input --> Data stored in some Service(factory) --> Data Passed to $scope --> >$scope value displayed in partial view (styled_form.html)
But I am lost as to how to dynamically store the user input inside of a service. Ideally this would all occur in realtime (as with the simple first example) as I would like to avoid having a refresh button. Could this be accomplished by creating a function in my controller that updates the values inside my service every few seconds? I need someone with better ideas than myself to point me in the right direction.
Question 2: Is this the correct workflow assuming Q1 is correct and if so what is the correct way to set up my service to handle the user input and pass it to another html page dynamically?
All help much appreciated
Having a service to store data and same controller to serve both view is fine.
Data saving could be done each time, when controller variables are changing.
When new controller is initialized, it my read the date from the service. A separate controller instance will be created for each view.
You may also check this blog to see, how data should be defined within a service, so that changing such data will auto-trigger controller to update view:
http://viralpatel.net/blogs/angularjs-service-factory-tutorial/
Notice: that service returns a reference to the array and controller saves this reference, when it is created.
Ok so I realized my problem was due to the fact that I was misunderstanding how $scope works in Angular not how $route.reload() was working. This topic
$scope variable not changing in controller when changed using directive
and this link in that question
https://github.com/angular/angular.js/wiki/Understanding-Scopes
helped me understand what I was doing wrong. $route.reload() and $templateCache.remove() were working correctly. The problem was that my $scope variable wasn't updating properly because each view was creating a different scope. Paraphrasing one of the links
The $scope is not the model.
The function of the controller is to write from the model to the scope
The function of the view is to display the $scope and write to the model if needed
I solved the problem using the controllerAS syntax discussed in the answers like this,
.controller('LivePreviewController',['$scope', function($scope) {
var vm = this;
vm.form_name = 'temporary name';
}]);
<!-- form_page.html -->
<div ng-controller="LivePreviewController as ctrl">
<input type="text" ng-model="ctrl.form_name>
And in my styled form partial view
<!-- styled_form.html -->
<div> {{ctrl.form_name}} </div>
This causes everything to work as expected
Pretty new to angular and having a little trouble getting data from controller and displaying in view using ionic.
I have a function in a controller ('DashCtrl') where I pass through a string to use within the function by using ng-click. For now I just want to take this string and display it in the next view as I have an href on the same element I have the ng-click event.
When I log the string on the next page, it is working and shows up. How do I get to use this in the view?
Heres the code:
HTML
*first page
<ul contentful-entries>
<div ng-repeat="story in $contentfulEntries.items">
<li class="story col col-100">
<a href="#/tab/story/{{story.fields.slug}}" ng-click='storyDetails("{{story.fields.title}}")'>
<p>{{ story.fields.title }}</p>
</a>
</li>
</div>
</ul>
*redirects to this on the ng-click
<ion-view view-title="Story">
<ion-nav-buttons side="left">
<button class="button back-button buttons button-clear header-item" ng-click="goBack()">
<i class="icon ion-ios-arrow-back"> Back</i>
</button>
</ion-nav-buttons>
<ion-content>
<ion-list ng-controller="DashCtrl">
<h1>{{ story.slug }} </h1>
<p> <!-- HERE IS WHERE I WANT TO DISPLAY THE STRING --> </p>
</ion-list>
</ion-content>
</ion-view>
*heres my controller
.controller('DashCtrl', function($scope, $stateParams, $ionicHistory) {
$scope.storyDetails = function($scope, details) {
// here is the data i need to display in the view
// the console.log shows up in the browser
console.log(details);
}
$scope.goBack = function(){
$ionicHistory.goBack();
}
// this is working fine
$scope.story = $stateParams;
})
Save the details string as a controller variable, and then you can access this within the view.
Assign variable details to some other variable like$scope.newVar = details and then in ur view you can display that by just binding it in this way {{newVar}}.
Hope you got it.
I ended up using the $rootScope. I know this may not be the best solution but I am just trying to grasp Angular at the moment.
In my controller I used
.controller('DashCtrl', function($scope, $stateParams, $rootScope, $ionicHistory) {
$scope.goBack = function(){
$ionicHistory.goBack();
}
$scope.storyDetails = function(details) {
$rootScope.details = details;
return $rootScope.details;
}
})
Then I am able to use the $rootScope.details in another controller to use in a function I need the string for.
I know I'm not doing this the Angular way, so if anyone would be kind enough to show me how to do this 'properly' without using the rootScope, I'd be forever in your debt.
I am having serious difficulties updating a view in Ionic/Angular when using ng-click.
I came across a similar issue earlier on but solved it following this guidance, which explains that if your button is inside a < label > ng-click will not work.
What am I trying to achieve?
I am developing a mobile application and want to allow a user edit their details if necessary. In an effort to start off most simply I have began by trying to implement the functionality whereby a user can edit their name. In the example below I am trying to change the name of the user when a button is clicked.
The strange thing is when I console.log(Photos.name) I get the correct value, i.e.(scope.user.name = "Jim") however the view does not reflect this change.
The code I have is as follows:
Controller
.controller('ProfileCtrl', function($scope, Photos) {
$scope.user = {
"name": Photos.name
}
$scope.changeName = function() {
Photos.changeName();
console.log(Photos.name)
};
})
Factory:
.factory('Photos', function(){
var o = {
name : 'James'
}
o.changeName = function(){
o.name = 'Jim'
}
return o;
});
HTML
Settings Template
This is where the button is that updates the user's name on the profile.html page(see below)
<ion-view view-title="Settings">
<ion-content>
<ion-list>
<div class="item item-input">
<span class="input-label">Change Profile Picture</span>
<button type="button" ng-click="changeName()">Add</button>
</div>
</ion-list>
</ion-content>
</ion-view>
Profile Template
<ion-view view-title="My Profile">
<ion-content class="padding">
<div class="item item-body">
<p class="profile-details">
{{user.name}}
</p>
</div>
</ion-content>
</ion-view>
I have read through many SO answers and those on the ionic webpage, with no luck. From what I have read I think that it may be something to do with setting the value in a child scope is the thing that is breaking it but I cannot be sure.
Can anyone help?
I believe the reason is that once you do this:
$scope.user = {
"name": Photos.name
}
You set the value of $scope.user.name to the value of Photos.name at that moment.
When you change Photos.name by doing o.name = 'Jim' within your factory, you're essentially assigning Photos.name a different string object, not changing the one that is already assigned to $scope.user.name.
You can prove my theory by doing something like $scope.user = Photos instead of $scope.user = { ... } (just as a quick proof of concept, of course, rather than a final solution). This way $scope.user.name will actually access the name value that's being held in the Photos factory.