I'm fairly new to Angular and very new to using the ui-router, so I could be missing something obvious.
If I launch my results.html page on its own, everything from the Web API is bound correctly through the controller and shows up as expected.
When I start from index.html and click on the button that calls $state.go(), I am navigated to the results.html page .. but none of the data from the controller shows up. The controller & service are still being called though - because I put console.log() statements to verify that the object I want is being returned after $state.go() and it is - the template just isn't registering it.
Here is my code for my ui-router and main controller:
// script.js
var app = angular.module('BN', ['ui.router']);
// configure our routes
app.config(function ($locationProvider, $stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('');
$stateProvider
.state('default',{
url:'/',
templateURL:'index.html',
controller: 'MainController'
})
.state('results', {
url:'/results',
controller: 'ResultsController',
controllerAs: 'vm',
templateUrl: 'Results/Results.html'
})
.state('instructor', {
url:'/api/instructors/:id',
templateUrl: 'Instructors/Instructor.html'
});
$locationProvider.html5Mode(true);
});
app.controller('MainController', MainController);
function MainController ($state) {
var vm = this;
vm.Submit=function( ){
$state.go('results');
};
}
So Results.html renders perfectly fine launched on it's own, but when navigated to - the controller is called but not bound to the html template.
You have your index.html file set up properly, but after that you're using ui-router incorrectly.
In your index.html file where you have:
<body ui-view>
this tells ui-router to load the contents of your templates into the body of your document, so your templates should just be snippets of html to be rendered within your body tag. So you should delete everything from results.html until all that remains is this:
<div id="headerBar" >
<div class="form-group" id="headerBar" >
<input class="form-control input-lg" type="text" id="inputlg" placeholder="Zipcode" />
<button id="sub" class="btn btn-default btn-lg" type="submit" ng-click="vm.getInstructors()">Find an Instructor!</button>
</div>
</div>
<table>
<tr ng-repeat="Instructors in vm.instructors">
<td style="padding-top:5px;">
<div>
<nav class="navbar">
<div class="container-fluid">
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" name="searchString" >
</div>
<button type="submit" class="btn btn-default" value="Filter">Search</button>
</form>
</div><!-- /.container-fluid -->
</nav>
</div>
</td>
</tr>
</table>
<div class="col-md-8">
</div>
<aside class="sidebar" ui-view="map">MAP</aside>
A few other things. You have the controller setup in your routes, so you don't need to specify it anywhere in results.html. Also you should not be able to navigate to results.html. Instead you would just navigate to (your domain)/results.
Related
When I click on continue button it checks clients ID in firestore database and if ID does'nt exist then $scope.filePath = "createClient.htm" is called. everything is working fine but when I call this piece of code inside firebase function nothing happens
Inside HTML
<div ng-include="filePath" class="ng-scope">
<div class="offset-1 offset-sm-2 col-11 col-sm-7">
<h2>Enter Client ID</h2>
<br>
<div class="form-group">
<label for="exampleInputEmail1">ID</label>
<input id="client_id" type="text" class="form-control" placeholder="Client ID">
</div>
<div class="float-right">
<button type="button" class="btn btn-danger">Cancel</button>
<button type="button" ng-click="searchClient()" class="btn btn-success">Continue</button>
</div>
</div>
</div>
Internal Script
<script>
$scope.searchClient = function()
{
//$scope.filePath = "createClient.htm"; it works here
var id= document.getElementById('client_id').value;
db.collection("clients") // db is firestore reference
.where("c_id","==",id)
.get()
.then(function(querySnapshot)
{
querySnapshot.forEach(function(doc)
{
if(!doc.exists)
{
console.log("Client Does'nt Exist");
$scope.filePath = "createClient.htm"; // but doesnt works here inside this firebase function
}
}
);
}
);
}
};
</script>
when console.log is shown and firebase function are fully executed then if I click on "Continue" Button again it works fine and content of createClient.htm is shown inside ng-include="filePath". why i need to click twice ?
I have an index page with <div ng-view></div> block in it. Here using $routeProvider various templates are inserted.
$routeProvider
// route for the home page
.when('/', {
templateUrl: 'templates/home.html',
controller: 'mainController',
css: 'css/style.css'
})
// route for the report page
.when('/report', {
templateUrl: 'templates/report.html',
controller: 'reportController',
css:['css/results.css','css/chart.css']
})
// route for the admin panel
.when('/adminpanel', {
templateUrl: 'templates/admin.html',
controller: 'adminController'
})
In one of the templates I have a form that upon submission calls a function using Angular ng-click="processPdf()".
<div class="remodal" data-remodal-id="download" role="dialog">
<button data-remodal-action="close" class="remodal-close"></button>
<h4 class="factor-title">Download Your PDF</h4>
<div class="window-message">
<form class="remodal-form" name="download-pdf" id="download-pdf">
<input type="email" placeholder="Enter your email" name="download-email" id="email" required>
<button ng-click="processPdf()" type="submit" class="download"><i class="fa fa-file-pdf-o fa-3x"></i> <span>Download PDF</span></button>
</form>
<button class="back-fixit" data-remodal-target="fixit"><i class="fa fa-long-arrow-left"></i> Back</button>
</div>
</div>
The problem is that once I call it, it provides invalid path: instead of saying /report/?email=zzz.com, it makes ?email=zzz.com/report even though the function is used on the report template. I have no clue what to do and any help will be appreciated.
some friends and I have started a team project but we are stuck at this point. We made a function of the site to add comments under every post. The problem is that when submit is clicked it adds the comment but doesn't refresh the page which causes some problems. The author stays "anonymous" and when refresh button is clicked it shows an alert:
The page that you're looking for used information that you entered. Returning to that page might cause any action you took to be repeated. Do you wish to continue?
However, if we just type the URL again and click ENTER everything is good: the author shows up and the comment appears only once. So the only solution for us is to redirect to the same page. Here is the form:
<div style="text-align: left">
<div><i>Leave your comment</i>
</div>
<form method="post">
<fieldset>
<p>
<textarea rows="10" class="form-control" type="text" id="1" name="commentText" style="height: 100px"></textarea>
</p>
<p>
<input type="submit" name="buttonSubmit" onclick="redirect" value="Add comment" class="btn btn-default" style="" />
</p>
</fieldset>
</form>
</div>
This is how the comments are printed on the page:
<h3>Comments</h3>
<br>
<div>
#foreach (var comment in ViewBag.Comments) {
<section class="row">
<article class="post col-md-12">
<div class="about">
Posted on <i>#comment.Date</i>
#if (comment.AuthorId != null) { #: by <i>#comment.Author.FullName</i>
}else { #: by <i>anonymous</i>
}
</div>
<div class="body">#comment.Text</div>
</article>
</section>
}
</div>
Thanks in advance!
Use the #Ajax.BeginForm() helper.
In the AjaxOptions(), you'll want to set the Httpmethod to "Post", InsertionMode.InsertBefore (or After depending on where you want new comments), and UpdateTargetId = "your-comment-div".
You'll need to include jquery.unobtrusive-ajax.js so the Ajax helper works correctly. You can use the nuget package manager to pull it in. Be sure to add it to your jquery bundle.
Then, you need to create the post action in your controller to accept the comment params and return a partial view.
Doing thIs keeps the Ajax confined to a razor helper and controller method.
View:
#using (Ajax.BeginForm("AjaxAddComment",
"MyController",
/* route params */,
new AjaxOptions()
{
InsertionMode = InsertionMode.InsertBefore,
UpdateTargetId = "commentsDiv",
HttpMethod = "Post"
}, htmlAttributes: new { /* ... */ }))
{
<div class="form-horizontal">
#* comment form... *#
</div>
}
...
<div id="commentsDiv">
<div class="comment">...</div>
<div class="comment">...</div>
</div>
Controller:
[HttpPost]
//[ValidateAntiForgeryToken]
public async Task<PartialView> AjaxAddComment(string comment, /*...other params*/)
{
var newComment = ... // comment viewModel
// add comment to db
await db.SaveChangesAsync();
return PartialView("_CommentPartial", newComment);
}
_CommentPartial:
<div class="comment">
...
</div>
I have looked for the solution in following two links:
how-to-access-rootscope-value-defined-in-one-module-into-another-module
rootscope-variable-exists-but-not-accessible
But still could not find a solution.
I initialize $rootScope.user variable in $scope.login function, which is triggered by some other button click event, of my controller as:
app.controller('LoginFormController',['$rootScope','$location','$log','$scope','userAngService','userBean',function($rootScope,$location,$log,$scope,userAngService,userBean){
$scope.login = function(val){
$scope.user = userAngService.login(val).then(function(data){
$rootScope.user = data;
$location.path("/home");
});
};
}]);
Redirecting it to /home mapped in app.js as:
angular.module('Writer', ['AllControllers','ngRoute'])
.config(['$routeProvider', function($routeProvider,$Log){
$routeProvider.when('/Diary',{
templateUrl:'login.html',
controller: 'LoginFormController'
})
.when('/home',{
templateUrl: 'home.html',
controller: 'ReachController'
})
.otherwise({redirectTo : '/Diary'});
}]);
Now I am accessing $rootScope.user variable in the mapped controller ReachController as:
app.controller('ReachController',['$scope','$rootScope',function($scope,$rootScope){
$scope.user = {};
$scope.user = $rootScope.user;
console.log($scope.user);
}]);
It is perfectly logging angular object in console but is not avaiable in my home.html page.
Here is the html page - accessing it in <h2> and <h3> tags:
<div>
<h2>{{$scope.user}}hhhello</h2>
<h3>{{$scope.user.author}}</h3>
<div id="welcomeStory">
<span id="wsTitleBub">Title</span>
<input id="wsTitle" type="text" ng-model="wsPublish.welcomeStoryTitle" />{{wsPublish.welcomeStoryTitle}}
<h6>Words..</h6>
<textarea id="wsWords" ng-model="wsPublish.welcomeStoryWords"></textarea>
<input id="wsPublish" type="button" name="wsPublish" value="Publish" ng-click="pub = !pub" />
<input id="wsAddShelf" type="button" name="wsAddToShelf" value="Add To Shelf" ng-click="addToShelf()" />
</div>
<div id="wsPublishTo" ng-show="pub">
<ul>
<li>
<input type=submit id="wsgroups" value="Group" ng-click="publishGroup(wsPublish)" />
</li>
<li>
<button id="wsPublic" ng-click="public()">Public</button>
</li>
</ul>
</div>
</div>
Just change your $scope.user to user in your markup and it'll work.
Once it is in $rootScope you can directly access it in markup with {{user}} no need to again assign it to scope variable!
My ASP.NET MVC application includes a Razor view with 3 tabs with a bunch of fields.
tab 1-2 has a bunch of fields
tab 3 should have a file upload section which should be rendered from a partial view.
Here is the structure:
<body>
<div class="container well" >
#using (Html.BeginForm(new { Action = "action X",id="publishingForm" })) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-horizontal">
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active"><span><strong>Step 1:</strong></span> Enter required fields</li>
<li><strong>Step 2:</strong> Enter optional fields</li>
<li><strong>Step 3:</strong> Upload your video</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="requiredtab">
</div>
<div class="tab-pane" id="optionaltab">
</div>
<div class="tab-pane" id="uplaodtab">
partial view here
</div>
</div>
</div>
</div>
}
</div>
</body>
</html>
As you can see the tab Divs are wrapped in a form (post to Controller X).
The problem is the partial view for the file upload also includes a form which should post to a handler. But when I initiate a file upload in Tab 3 it is attempting to post to Controller X of the original form.
How can I structure my view to have the fields included in the form on tabs 1 & 2 post to Controller X and the Form in Tab 3 post to its correct handler?
The bottom line is I am trying to post separately to 2 different forms included in different tab panels
i suggest that you wrap your two forms with Ajax Forms, and you can submit them both asynchronously
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "updateDiv" }))
{
<input type="submit" id="submitForm1" value="OK" />
}
<div id="updateDiv"></div>
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "updateDiv2" }))
{
<input type="submit" id="submitForm2" value="OK" />
}
<div id="updateDiv2"></div>
and call the .click() for each submit button whenever your code needs to.