Dynamically loading content within a partial view - javascript

Basically, I am trying to implement tabs on a main page. The tabs will consist of components on other pages for quick access. I am confused on how I can import a layout while sending data to it in a "lazy" way.
I now use the #section tag to bring in the layout, which is fine. But I only want to request the data it needs when the tab is clicked.
in my main.blade.php:
<li>
<a href="#tab_1" data-controller="tab_1" data-target="#tab_1" data-toggle="tab" aria-expanded="true">
tab 1 </a>
</li>
<div class="tab-pane" id="tab_1" >
#yield('tab_1')
</div>
in my tab1:
#extends('main')
#section('tab_1')
#foreach ($activities as $activity)
{{--implementation--}}
#endforeach
#endsection
in my TabController#showtab1:
public function showtab1(Request $request) {
//Logic here
return view('tab1', ['activities' => $activities]);
}
The optimal scenario is loading the content for each tab only when the tab is clicked by calling a controller function. I have gotten it to work by using routes to change the whole page, but it kind of ruins the advantage of tabs.

You would typically implement this in such a way that you use the same layout, then pass a different parameter through your URL -> controller -> blade include parameter -> blade view.
The example below demonstrates how you can do 'lazy'-load (load only 1 tab at the same time) across files in Laravel:
// /routes/web.php
Route::get('/tabbed-page', 'TabbedPageController#index');
Route::get('/tabbed-page/:tab', 'TabbedPageController#show');
// /App/Http/Controllers/TabbedPageController.php
public function show($request, $tab) {
$data = ['title'=> 'No tab'];
if ($tab === 'tab1') {
$data = ['title' => 'I am tab 1'];
}
return view('page', [
'tab' => $tab,
'data'=> $data
]);
}
public function index($request) {
// open tab1 by default
redirect('/tabbed-page/tab1');
}
{{-- /resources/views/page.php, requested at for example /tabbed-page/tab1 --}}
<nav>
Tab 1
Tab 2
Tab 3
Tab 4
</nav>
<main>
#include($tab, $data)
</main>
{{-- /resources/views/tab1.php, tab2.php, tab3.php, etc.. --}}
<div id="tab1">
<h1>{{ $data['title] }}</h1>
Content ....
</div>

Related

JSON data in a list duplicating with Grails <g:each> incorporation

I am displaying a dynamic list of concerts, from a JSON source, on a page. These are also being added to my database from this source, but are not being displayed from my database on this page, for various reasons.
I want to include a link to the show page for each database concert in the list of concerts being displayed via JSON.
This acquires my JSON concerts:
function fetch(){
if($scope.search == "" || $scope.search == null){
$.getJSON("http://api.bandsintown.com/events/search.json?&api_version=2.0&app_id=FYP&location=Dublin,Ireland", function(result)
{
$scope.$apply(function()
{
$scope.details = result;
changeDate();
}, 0);
});
}
The concerts from that JSON are the next 50 gigs, so I have acquired links to the show pages to the last 50 concert entries to my database, which will match the JSON, like so:
def index()
{
int eventCount = Event.count()
int startingPoint = eventCount - 50
def events = Event.createCriteria().list
{
order('id')
firstResult(startingPoint)
maxResults(50)
}
respond events
}
Trying to combine the JSON and the show links results in the two loops clashing and a 50 x 50 list results on the page - with each JSON entry have a link to each show or vice versa.
<ul class="rel-results">
<g:each in="${eventInstanceList}" status="i" var="eventInstance">
<li ng-repeat="show in details">
<!-- SHOW LINKS -->
<g:link action="show" controller = "Event" id="${eventInstance.id}">Info</g:link>
<div class = "event-date-time">{{ show.datetime }}</div>
<div class = "event-item">
<div class = "nameAndTicket row" style="margin-left: 0;margin-right: 0">
<span class="artist-name col-md-10">
<a href="#/" id="{{ $index + 1 }}" ng-click="update(show)" class = "artist-item">
{{ show.artists[0].name }}
</a>
</span>
</div>
<div class="venueAndRSVP row" style="margin-left: 0;margin-right: 0">
<span class="venue-name col-md-10">
<a href="#/" id="{{ $index + 1 }}" ng-click="update(show)" class = "venue-item">
<div style = "text-transform: lowercase;display: inline-block;color: red;font-size: 80%;">at</div> {{ show.venue.name }} {{ show.formatted_location }}
</a>
</span>
</div>
</div>
</li>
</g:each>
</ul>
I have tried Angular unique filters and even hacky JS to remove duplicate links on a page, but I think these are the wrong ideas. I feel like I need to combine the g:each and the ng-repeat somehow - actually doing so does not work.
Any help would be greatly appreciated!
EDIT to add Event domain
class Event implements Rateable, Commentable {
int bandsintown_id
String artist
String venue
String ticket_url
String ticketStatus
String eventTime
String livestream
static constraints =
{
bandsintown_id unique:true
livestream nullable:true
}
The id from the json is stored in your Event domain so that is the best/most unique thing to use to link the 2 together, this works for me...
EventController
def showByBandId() {
def event = Event.findByBandsintown_id( params.id )
// add some error handling here in case event isn't found
redirect ( action: 'show', id: event.id )
}
homepage.gsp
<div id="related_results">
<g:render template="partials/shows" />
</div>
shows.gsp
...
<li ng-repeat="show in details">
<a ng-href="${createLink( controller: 'event', action: 'showByBandId' )}/{{show.id}}">Info</a>
....

Angularjs nested controller called just one time

I'm new in Angularjs and I have an app, with some "projects", which have a local menu displayed on some pages. Index.html contains the main navbar with footer :
<body ng-app="ysi-app" ng-controller="MainController">
<div class="page-content">
<div class="row">
<div class="col-md-2">
<div class="sidebar content-box" style="display: block;">
<ul class="nav">
<!-- Main menu -->
<li ng-if="isAuthenticated()">{{name}}</li>
<li class="current">Dashboard</li>
<li>Projects</li>
</ul>
</div>
<div ng-if="isAuthenticated() && displayProjectMenu == true" ng-include="'views/localMenu.html'" ng-controller="LocalMenuController">
</div>
</div>
<div ng-view></div>
</div>
So I have a nested controller LocalMenuController for the local menu and a main controller. The project controller sets the datas :
angular.module('ProjectCtrl',[]).controller('ProjectController',function($scope,$location, ProjectService,$route, AuthenticationService, $rootScope){
$scope.setProjectDatas = function(projectName, projectId){
ProjectService.setName(projectName);
$rootScope.projectId = projectId;
};});
I set the id of one project to the $rootScope for testing (I have a Service which will do that better) and get it in the LocalMenuController :
angular.module('LocalMenuCtrl',[]).controller('LocalMenuController', function($scope, ProjectService, $rootScope) {
$scope.projectId = '';
$scope.projectId = $rootScope.projectId;
});
I display projects in a table and when I clicked on one of it, the function setProjectDatas(name,id) is called. The problem is when I clicked on one project, the id of the project is correct and set but when I go previous and clicked on another project, the id is the old id of the project previously clicked. The datas are not updating. I googled my problem but found nothing on it.
I think the LocalMenuController is called only one time but not after.
What am I doing wrong ?
Thank you
UPDATE
I've created a Directive which displays the template but it's still not updating the partial view localMenu.
LocalMenu Directive :
angular.module('LocalMenuCtrl',[]).controller('LocalMenuController', function($scope, ProjectService, $rootScope) {
console.log('-> LocalMenu controller');
})
.directive('localMenu', function($rootScope){
return {
templateUrl: '/YSI-Dev/public/views/partials/localMenu.html',
link: function(scope){
scope.projectId = $rootScope.projectId;
}
};
});
A part of index.html
<div ng-if="isAuthenticated() && displayProjectMenu == true" ng-controller="LocalMenuController">
<div local-menu></div>
</div>
Partial view localMenu :
<div class="sidebar content-box" style="display: block;">
<ul class="nav">
<li><i class="glyphicon glyphicon-list-alt"></i> Backlog</li>
<li><i class="glyphicon glyphicon-user"></i> My team </li>
</ul>
</div>
I'm trying to get the projectId from the $rootScope and inject it in the <a href="#/project/{{projectId}}" but I have some troubles. What's the way to do that ?
First of all, try using directives instead of ng-controller. You can encapsulate your code and template into a unit. You can also try creating a component. Pass some data to the directive/component and Angular will take care of updating the template and running whatever needs to run within the directive/component. (Given that you used two-way data-bindings)
From the code above, I cannot see what would trigger LocalMenuController to run again.

AngularJS : ng-switch is not triggering when i was clicking second time?

I have a left nav in my one of the view of the application whiich is build using ng-repeat and ng-switch. every link's action associate to a directive in the right hand side. some time, the particular directive will include other directive when user click on the dropdown items from the current directive and page gets extended long and long , so if user want to go to the original state then he can click on the nav item from the left nav to refresh the page to the initial state of the directive. But whenever user clicks on the left nav second time when the left nav already selected, it is not get triggered.I want this get tirggered to bring my initial page of the RHS.
My highlevel code as follows
about.html
<div class="leftNav">
<ul class="nav myNav">
<li class="presentation" ng-repeat="link in links" ng-class="{link-active:currentLink=link.value==param}">
<a ng-href="#/home/{{link.value}}" ng-click="fetchLink(param)">{{link.title}}</a>
</li>
</ul>
</div>
<div ng-switch="fetchLink()">
<div ng-switch-when="About Us">
<div about-us></div>
</div>
<div ng-switch-when="Board Directors">
<div board-directors></div>
</div>
<div ng-switch-when="Our Impacts">
<div our-impacts></div>
</div>
</div>
aboutController.js
$scope.links = [{ title="About Us", value="about"},
{ title="Board Directors",value="board"},
{ title="Our Impacts", value="impact"} ];
var myParam =$root.current.params;
$scope.param = myParam.sec;
//sec has been configured in the route and get
// the values from user's input
$scope.fetchLink() = function() {
var retVal='';
var retVals = $.grep($scope.links, function(item,ind){
return item.value=$scope.param
});
if(retVals.length>0){
retVal = retVals[0].title;
}
return retVal;
};
};
On the router code of app.js
$routeProvider
.when('/about/:sec', {
templateUrl : 'app/view/about.html',
controller: 'aboutController.js'
});
}
When i click the second time, nothing get triggered and fetchLink() method is not triggered.

View different HTML pages?

I wanted to view different HTML pages based on what a user clicks. For example, I have three tabs set up as so:
<div class="span7" >
<ul class="nav nav-tabs" style="margin-bottom: 5px;">
<li class="active">First</li>
<li>Second</li>
<li>Third</li>
</ul>
<div class="span12" style="margin-left:0;" ng-grid="gridOptions"></div>
</div>
And I merely want to view a different page based off of what the individual clicks. For example, if he clicks First, he will see First's html page where source.sourceObject in the code below denotes which html page to view. It is written like so:
<div class="span5">
<div class="edus-activity-container">
<div ng-show="sourceViewState.selected" class="edus-admin-activities-grid" />
</div>
<div ng-include="'/partials/' + source.sourceObject + '.html'"/>
</div>
where in my javascript file, source.sourceObject is defined based off of if I click the First, Second or Third tab. However, my implementation is not working. I made sure I had no typos in the spelling of my files in source.sourceObject. Any ideas on how to do so?
In your controller:
var pages = { 'one': 'partials/one.html', 'two':'partials/two.html' }
$scope.currentPage = pages['one'] ; //This is required if you want a default page
$scope.first = function(){ $scope.currentPage = pages['one']; }
$scope.two = function(){ $scope.currentPage = pages['two']; }
In your template/HTML
<div ng-include="currentPage"/>

From submit in a AJAX-generated tabs (Twitter Bootstrap)

I'm trying to submit a from which is located into a tabs. This tabs content is generated via AJAX.
My problem is that when I submit the form, the page refresh and the "default" tab is loaded so the php function generating the tab with the form never receive the post data.
Here the solutions I though about :
1) The easiest : Finding a way to insert a hash in the URL so that when the page refresh, a javascript code load the good tab.
2) The best (considering user experience) : Finding a way to submit the form with ajax and add the new entry to the list under the form in the tab. BUT I want to use php to check form values (is_empty(), etc.). I thought about sending data to the php controller, then, hide the form and replace it with the new form generated by the php controller (with error messages or empty fields if fields were ok and data added to the DB).
Here is my code :
The layout :
<ul class="nav nav-tabs" id="myTabs">
<li class="active">Profile</li>
<li>About</li>
<li>Wishlists <span class="badge"><?= $profile['wishlists'] ?></span></li>
<li>Following <span class="badge"><?= $profile['following'] ?></span></li>
<li>Followers <span class="badge"><?= $profile['followers'] ?></span></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane active" id="profile">Profile</div>
<div class="tab-pane" id="about">about</div>
<div class="tab-pane" id="wishlist">wl</div>
<div class="tab-pane" id="following">following</div>
<div class="tab-pane" id="followers">followers</div>
</div>
The tab :
<?php
if($owner)
{ ?>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<form class="form-horizontal" role="form" method="post">
<fieldset><legend>Add a wishlist</legend>
<?php echo $form; ?>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default" name="addwishlist">Add</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
<hr />
<?php
}
?>
<div class="row">
<?php
foreach($wishlists as $wishlist)
{ //Here we display whislists } ?>
The php controller that corresponding to the tabs view :
$manager = $this->managers->getManagerOf('Wishlist');
/**
* Adding a new wishlist
*/
if($owner)
{
//Creating object. Depends on form validation
if ($request->postExists('addwishlist'))
{
$wishlist = new \Lib\Entities\Wishlist(array(
'title' => $request->postData('title'),
'comment' => $request->postData('comment'),
'user' => $this->app->user()->getUser(),
));
}
else
{
$wishlist = new \Lib\Entities\Wishlist;
}
//generating form
$formBuilder = new \Lib\Forms\WishlistForm($wishlist);
$formBuilder->build();
$form = $formBuilder->form();
$formHandler = new \Lib\FormHandler($form, $manager, $request);
//if form has been validate : add the wishlist and set flash
if ($formHandler->process('add'))
{
$this->app->user()->setFlash('Your wish list has been created !');
$this->app->httpResponse()->redirect('/Shawili/'.$request->getData('user').'/wishlists/');
}
$this->page->addVar('form', $form->createView());
}
/**
* Displaying user's wishlists
*/
$wishlists = $manager->getWishlists($request->getData('user'), $this->app->user()->getUser());
$this->page->addVar('wishlists', $wishlists);
$this->page->addVar('owner', $owner);
$this->page->addVar('profile', $request->getData('user'));
$this->page->addVar('cuser', $this->managers->getManagerOf('User')->getUser($this->app->user()->getUser()));
The Jquery code :
<script type='text/javascript'>
$('#myTabs a').click(function (e) {
e.preventDefault();
var url = $(this).attr("data-url");
var href = this.hash;
var pane = $(this);
// ajax load from data-url
$(href).load(url,function(result){
pane.tab('show');
});
});
// load first tab content
$('#profile').load($('.active a').attr("data-url"),function(result){
$('.active a').tab('show');
});
</script>
Any suggestion of the best way to do that?
Second option is rather widely used practice and it always works well, so you can use it without concern.
Looking at your code I suppose, that you want to generate form code and send it via ajax to browser. It is not necessarily best way to do it. You don't have to hide and replace form. You can easyly modify existing one with jQuery.
The trick is to send to the browser only formated data containing info about errors etc. (for example using JSON) and then decode it (jQuery way) and localy modify content of web page.
To submit form via ajax you can just overwrite click event for the button and then collect data from fields and send it to the server, for example like this:
$("#submit_button_id").click(function(){
var formdata = $("#form_id").serializeArray();
$.ajax({
url: "/submit_url",
data: formdata,
success: function(RESPONSE){
//Your code to modify page content after geting RESPONSE.
}
})
return false; //To prevent page from reloading
}

Categories