I have spent the last few days monkeying with my app, trying to figure out how best to keep track of an editing state within a given controller. Of course, the problem is, multiple of these ObjectControllers exist at one time, and only one can be editing at a given moment. Below is the important code:
App.js:
var App = Ember.Application.create();
//ROUTES
App.Router.map(function() {
this.resource('tasks', function() {
this.resource('task', {path: ':task_id'});
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('tasks');
}
});
App.TasksRoute = Ember.Route.extend({
model: function() {
return App.Task.find();
}
});
App.TaskRoute = Ember.Route.extend({});
//CONTROLLERS
App.TasksController = Ember.ArrayController.extend({
isEditing: null,
editing: false,
newTask: function() {
console.log('new task');
},
toggleEdit: function(id) {
this.set('isEditing', id);
if ($('#collapse' + this.get('isEditing')).hasClass('in')) {
this.set('editing', false);
this.set('isEditing', null);
$('.in').collapse('hide');
} else {
this.set('editing', true);
$('.in').collapse('hide');
$('#' + 'collapse' + this.get('isEditing')).collapse('toggle');
}
}
});
App.TaskController = Ember.ObjectController.extend({
needs: 'tasks',
collapseId: function() {
return "collapse" + this.get('id');
}.property('id'),
collapseHref: function() {
return "#collapse" + this.get('id');
}.property('id'),
});
//VIEWS
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
var self = this;
Ember.run.schedule('afterRender', function() {
self.$('.navbar').affix({offset: -1000});
});
}
});
//HANDLEBARS HELPERS
//STORE DEFINITION
App.Store = DS.Store.extend({
revision: 11,
adapter: 'DS.FixtureAdapter'
/*DS.RESTAdapter.extend({
url: 'http://localhost:3000'
})*/
});
//MODELS
App.Task = DS.Model.extend({
summary: DS.attr('string'),
description: DS.attr('string'),
start: DS.attr('string'),
end: DS.attr('string'),
recurrence: DS.attr('string')
});
//FIXTURE DATA
App.Task.FIXTURES = [{
id: "q5ji9chrh1hcu05dohvrf4aumc",
summary: "Test",
description: null,
start: "2013-04-01T10:00:00-07:00",
end: "2013-04-01T11:00:00-07:00",
recurrence: "FREQ=WEEKLY;BYDAY=MO,WE,TH,FR"
}, {
id: "mm4m3pq6icbgbl6m49jpdhi8j0",
summary: "Test 2",
description: "absafdaerwer",
start: "2013-04-01",
end: "2013-04-02",
recurrence: null
}];
Home.HTML:
<!--TEMPLATES-->
<script type="text/x-handlebars">
<div class="navbar" data-spy="affix">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
</div>
</div>
</div>
{{outlet}}
</script>
<script type="text/x-handlebars" id="tasks">
<div class="row-fluid span8 offset2 task-list">
<div class="space-top"><div>
<div class="accordion" id="accordion">
{{partial 'tasks/newTask'}}
{{#each task in controller}}
<div class="accordion-group">
{{render 'task' task}}
</div>
{{/each}}
</div>
</div>
</script>
<script type="text/x-handlebars" id="tasks/_newTask">
<div class="accordion-group">
<div class="new-task-header accordion-heading" {{action newTask on="click"}}>
<span class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapseNew">New Task...</span>
</div>
<div id="collapseNew" class="accordion-body collapse">
<div class="new-task accdion-inner">
{{#if task.description}}
<p>{{task.description}}</p>
{{else}}
<p>No description</p>
{{/if}}
</div>
</div>
</div>
</script>
<script type="text/x-handlebars" id="task">
<div class="task">
{{#linkTo 'task' task}}
<div class="accordion-heading" {{action toggleEdit task.id on="click"}}>
<span class="accordion-toggle" data-toggle="collapse" data-parent="#accordion">
{{#if controllers.tasks.editing}}
editing {{task.summary}}
{{else}}
{{task.summary}}
{{/if}}
</span>
</div>
{{/linkTo}}
</div>
<div {{bindAttr id="collapseId"}} class="accordion-body collapse">
<div class="edit-task accdion-inner">
{{#if task.description}}
<p>{{task.description}}</p>
{{else}}
<p>No description</p>
{{/if}}
</div>
</div>
</script>
In this code, there are not multiple TaskControllers being created, I believe. Try setting itemController: 'task' on the ArrayController. (Discussed here, and if you're using 1.0.0-rc.2 see mention here.) That way you can set an editing property on that particular task (and reference tasks if needed). Does that clear anything up?
Related
I have a main app page component with a search bar. The Search results that come back is in cards And I am looking to set up a "Click here to view more detail" that would be placed in each card. And it would link to the Details page of the one result clicked. How do I link these components on Vue and if the id could be passed? I am hoping that upon click of the button the component renders on the same page and not a new tab.
Once I click on "click here" It updates the link to http://localhost:8081/#/{name:'Details',%20params:%20{id:%20result._gddid}}
and
I get an [Vue warn]: Property or method "results" is not defined on the instance but referenced during render.
Thank you!
app.vue
<template>
<div id="app">
<Header/>
<SearchForm v-on:search="search"/>
<SearchResults
v-if="results.length > 0"
v-bind:results="results"
v-bind:reformattedSearchString="reformattedSearchString"/>
<Details
v-bind:results="results"
/>
<Pagination
v-if="results.length > 0"
v-bind:prevPageToken="api.prevPageToken"
v-bind:next_page="api.scrollId"
v-on:prev-page="prevPage"
v-on:next-page="nextPage"
/>
</div>
</template>
<script>
import Header from './components/layout/Header';
import SearchForm from './components/SearchForm';
import SearchResults from './components/SearchResults';
import Details from './components/Details'
import Pagination from './components/Pagination';
import axios from 'axios';
export default {
name: 'app',
components: {
Header,
SearchForm,
SearchResults,
Details,
Pagination
},
data() {
return {
results: [],
reformattedSearchString: '',
api: {
baseUrl: 'https://test.org/api/v1/articles?',
max: 25,
q: '',
prevPageToken: '',
scrollId: ''
}
};
},
methods: {
search(searchParams) {
this.reformattedSearchString = searchParams.join(' ');
this.api.q = searchParams.join('+');
const { baseUrl, q, max} = this.api;
const apiUrl = `${baseUrl}&term=${q}&title_like=${q}&recent&max=${max}&full_results`;
this.getData(apiUrl);
},
prevPage() {
const { baseUrl, q, max, prevPageToken } = this.api;
const apiUrl = `${baseUrl}&term=${q}&title_like=${q}&max=${max}&pageToken=${prevPageToken}`;
this.getData(apiUrl);
},
nextPage() {
const { baseUrl, q, max,scrollId } = this.api;
const apiUrl = `${baseUrl}&term=${q}&title_like=${q}&max=${max}&recent&full_results&scroll_id=${scrollId}`;
this.getData(apiUrl);
},
getData(apiUrl) {
axios
.get(apiUrl)
.then(res => {
this.results = res.data.success.data;
this.api.prevPageToken = res.data.success.data.prevPageToken;
this.api.next_page = res.data.scrollId;
})
.catch(error => console.log(error))
}
}
};
</script>
SearchResults.vue
<template>
<div class="container mb-3">
<div class="d-flex mb-3">
<div class="mr-auto">
<h3>Search Results for "{{ reformattedSearchString }}"</h3>
</div>
<div class="btn-group ml-auto" role="group">
<button
#click="changeDisplayMode('grid')"
type="button"
class="btn btn-outline-secondary"
v-bind:class="{ active: displayMode === 'grid' }"
>
<i class="fas fa-th"></i>
</button>
<button
#click="changeDisplayMode('list')"
type="button"
class="btn btn-outline-secondary"
v-bind:class="{ active: displayMode === 'list' }"
>
<i class="fas fa-list"></i>
</button>
</div>
</div>
<div class="card-columns" v-if="displayMode === 'grid'">
<div class="card" v-bind:key="result._gddid" v-for="result in results">
<ArticleGridItem v-bind:result="result"/>
</div>
</div>
<div v-else>
<div class="card mb-2" v-bind:key="result._gddid" v-for="result in results">
<ArticleListItem v-bind:result="result"/>
</div>
</div>
<div class="card mb-2" v-bind:key="result._gddid" v-for="result in results">
<Details v-bind:result="result"/>
</div>
</div>
</template>
<script>
import ArticleListItem from './ArticleListItem';
import ArticleGridItem from './ArticleGridItem';
import Details from './Details';
export default {
name: 'SearchResults',
components: {
ArticleListItem,
ArticleGridItem,
Details,
},
data() {
return {
title: 'Search Results',
displayMode: 'grid'
};
},
methods: {
changeDisplayMode(displayMode) {
this.displayMode = displayMode;
}
},
props: ['results', 'reformattedSearchString']
};
</script>
<style scoped>
button:focus {
box-shadow: none !important;
}
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router';
import moment from 'moment'
Vue.config.productionTip = false
Vue.filter('formatDate', function (value) {
if (!value) return ''
return moment(value.toString()).format('MM/DD/YYYY hh:mm')
})
Vue.use(VueRouter)
import Details from './components/Details';
const router = new VueRouter({
routes: [
{
path: '/Details/:id',
name: 'Details',
component: Details
}
]
})
new Vue({
router,
render: h => h(App),
}).$mount('#app')
ArticleListItem.vue
<template>
<div>
<div class="card-body">
<h6 class="card-text">{{ result.title }}</h6>
<p class="card-subtitle mb-2 text-muted"
>{{ result.publisher }} | {{ result.journal }} | {{ result.year }}</p>
<a :href="'https://test.org/api/articles?docid=' + result._gddid" target="_blank">
<i class="fa fa-download" alt="Download"> </i>
</a>
<router-link dark to="{name:'Details', params: {id: result._gddid}}">
Click here for more Details
</router-link>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: 'ArticleListItem',
props: ['result'],
}
</script>
Details.vue
<template>
<div class="Details">
<div class="container">
<div class="row">
<div class="col-md-12" v-for="result in results" :key="result._gddid">
<div v-if="id == result._gddid">
<h1>{{result.title}}</h1>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Details',
props: ['result'],
};
</script>
Once I click on "click here" It updates the link to http://localhost:8081/#/{name:'Details',%20params:%20{id:%20result._gddid}}
Glancing over the code it appears that within ArticleListItem.vue the router-link's to attr isn't bound so it's treated as a string.
Currently: to="{name:'Details', params: {id: result._gddid}}"
Try: :to="{name:'Details', params: {id: result._gddid}}" so it's passed as an object.
I get an [Vue warn]: Property or method "results" is not defined on the instance but referenced during render.
Within Details.vue you have props: ['result'], but in the v-for it looks for results which isn't defined within data() nor within props.
As for the # appearing, vue-router's default mode is hash, if you're not wanting to use # you can set it to history via:
const router = new VueRouter({
mode: 'history',
routes: [...]
})
But beware you'll need a server running to handle the routing; You can find more info at https://router.vuejs.org/guide/essentials/history-mode.html#html5-history-mode
I have a form in one tab and list of applications submitted in another tab.
If I click edit on a form, I should load the data from database and go to the other tab. On ng-click , I am able to retrieve the data but not able to change the tab.
Here are the relevant files:
navbar.html
<nav class="navbar navbar-default navbar-cls-top " role="navigation" style="margin-bottom: 0">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".sidebar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html"></a>
</div>
<div class="header-right">
<i class="fa fa-sign-out fa-2x"></i>
</div>
</nav>
<!-- /. NAV TOP -->
<nav class="navbar-default navbar-side" role="navigation" style="width:200px">
<div class="sidebar-collapse">
<ul class="nav" id="main-menu">
<li>
<div class="inner-text">
{{user.name}}
<br />
<small> </small>
</div>
</div>
</li>
<li>
<a id="page1" ng-class='{"active-menu": selectedMenu == "dashboard"}' ui-sref="secured.dashboard" ng-click='selectedMenu = "dashboard"'><i class="fa fa-dashboard "></i>Dashboard</a>
</li>
<li>
<a id="page2" ng-class='{"active-menu": selectedMenu == "applicationForm"}' ui-sref="secured.applicationForm" ng-click='selectedMenu = "applicationForm"'><i class="fa fa-handshake-o "></i>Application Forms</a>
</li>
<li>
<a ng-class='{"active-menu": selectedMenu == "logout"}' href="" ng-click="logout()" ng-click='selectedMenu = "logout"'><i class="fa fa-sign-out fa-fw"></i> Logout</a>
</li>
</ul>
</div>
</nav>
dashboard.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dashboard For Applications</title>
</head>
<body>
<div id="wrapper">
<div id="page-wrapper">
<div id="page-inner">
<div class="row">
<div class="col-md-12">
<h1 class="page-head-line">
<div class="alert alert-danger">
DASHBOARD
</div>
</h1>
<h1 class="page-subhead-line">
<div class="alert alert-info">
Welcome! Here is the list of applications you have saved or submitted. <br><br>
</div>
</h1>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3>Applications List</h3>
</div>
<div class="panel-body">
<table ng-if="applicationList" st-table="applicationTable" class="table table-striped">
<tr>
<th>Application Number</th>
<th>Project Title</th>
<th>Project Description</th>
<!-- <th>DataSet Available</th> -->
<!-- <th>Impact</th> -->
<th>Number of Interns</th>
<th>Expected SkillSet</th>
<th>Software Licenses Needed</th>
<th>Hardware Requirements</th>
<th></th>
<th></th>
</tr>
<tbody>
<tr ng-repeat="application in applicationList">
<td class="col-md-2">{{application.number}}</td>
<td class="col-md-2">{{application.title}}</td>
<td class="col-md-2">{{application.description}}</td>
<!-- <td><span ng-repeat='area in idt.areas'>{{area}}, </span></td> -->
<!-- <td class="col-md-2">{{application.technical}}, {{application.business}}</td> -->
<td class="col-md-2">{{application.numberOfInterns}}</td>
<td class="col-md-2">{{application.skillSet}}</td>
<td class="col-md-2">{{application.software}}</td>
<td class="col-md-2">{{application.hardware}}</td>
<td><button class="btn btn-danger" ng-click="remove(application._id)" ng-show="application.state=='saved'">Delete</button></td>
<td><button class="btn btn-warning" ng-click="selectedMenu='applicationForm'; edit(application._id)" ng-show="application.state=='saved'">Edit</button></td>
<!-- <td><button class="btn btn-warning" ng-click="selectedMenu='dashboard'; edit(application._id)" ng-show="application.state=='saved'">Edit</button></td> -->
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- /. ROW -->
<hr />
</div>
<!--/.ROW-->
</div>
<!-- /. PAGE INNER -->
</div>
<!-- /. PAGE WRAPPER -->
</div>
<!-- /. WRAPPER -->
</body>
</html>
dashboard.js :
(function() {
var app = angular.module('dashboard', []);
app.config(['$stateProvider', function($stateProvider) {
$stateProvider.state('secured.dashboard', {
url: '/dashboard',
controller: 'DashboardController',
templateUrl: '/views/dashboard.html'
});
}]);
app.controller('DashboardController', ['$scope', 'AuthService', 'user', '$state', '$http', function($scope, AuthService, user, $state, $http) {
$scope.user = user;
AuthService.setUser(user);
$scope.logout = function() {
AuthService.logout().then(function() {
$scope.user = null;
$state.go('unsecured');
})
}
var refresh = function(){
$http.get('/application/applicationList').then(function(response){
console.log("I got the applications I requested");
$scope.applicationList = response.data;
console.log($scope.applicationList);
$scope.pagination = {};
// $scope.totalItems = 200;
$scope.pagination.currentPage = 0;
$scope.numPerPage = 10;
});
};
refresh();
$scope.remove = function(id){
var del = false;
swal({
title: 'Are you sure?',
text: "You won't be able to revert this!",
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
focusCancel: true,
allowEscapeKey: true,
allowEnterKey: true,
allowOutsideClick: true,
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!',
cancelButtonText: 'No, cancel!',
confirmButtonClass: 'btn btn-success',
cancelButtonClass: 'btn btn-danger',
buttonsStyling: false
}).then(function () {
$http.delete('/application/applicationlist/'+id).then(function(response){
clear();
refresh();
});
swal(
'Deleted!',
'Your Application has been deleted.',
'success'
)
}, function (dismiss) {
// dismiss can be 'cancel', 'overlay',
// 'close', and 'timer'
if (dismiss === 'cancel') {
swal(
'Cancelled',
'Your Application is safe :)',
'error'
)
}
})
};
$scope.edit = function(id){
console.log(id);
console.log("Edit function called");
$http.get('/application/applicationList/'+id).then(function(response){
$scope.application = response.data;
console.log($scope.application);
//refresh();
$scope.changeTab(event, 'page1');
});
};
var clear = function(){
$scope.application = {
technical: false,
business: false
};
};
}]);
})();
applicationForm.js:
(function() {
var app = angular.module('applicationForm', []);
app.config(['$stateProvider', function($stateProvider) {
$stateProvider.state('secured.applicationForm', {
url: '/applicationForm',
controller: 'applicationFormController',
templateUrl: '/views/applicationForm.html'
});
}]);
app.controller('applicationFormController', ['$http', '$scope', '$state', '$uibModal', function($http, $scope, $state, $uibModal) {
$scope.application = {
technical: false,
business: false
};
var refresh = function(){
$http.get('/application/applicationList').then(function(response){
console.log("I got the applications I requested");
$scope.applicationList = response.data;
console.log($scope.applicationList);
$scope.pagination = {};
// $scope.totalItems = 200;
$scope.pagination.currentPage = 0;
$scope.numPerPage = 10;
});
};
refresh();
$scope.saveApplication = function(){
console.log($scope.application);
console.log($scope.applicationList);
var check = 0;
$scope.application.state = "saved";
$scope.application.userEmail = $scope.user.email;
for (var i=0, len=$scope.applicationList.length; i < len; i++) {
if ($scope.applicationList[i]._id == $scope.application._id) {
check = 1;
console.log("matched");
break;
}
}
if(check == 1){
$http.put('/application/applicationlist/' + $scope.application._id, $scope.application).then(function(response){
//$scope.contact = response.data;
refresh();
});
}
else{
$http.post('/application/applicationList', $scope.application).then(function(response){
console.log(response);
refresh();
});
}
swal({
title: "Great!",
text: "We have saved your application",
type: "success",
timer: 3000,
confirmButtonText: "Wohoo!"
});
clear();
};
$scope.submitApplication = function(){
console.log("Submit called");
console.log($scope.application.title);
console.log($scope.user.email);
$scope.application.userEmail = $scope.user.email;
$scope.application.state = "submit";
var check = 0;
for (var i=0, len=$scope.applicationList.length; i < len; i++) {
if ($scope.applicationList[i]._id == $scope.application._id) {
check = 1;
console.log("matched");
break;
}
}
if(check == 1){
$http.put('/applicationlist/' + $scope.application._id, $scope.application).then(function(response){
refresh();
});
}
else{
$http.post('/application/applicationList', $scope.application).then(function(response){
console.log("Successfully submitted");
refresh();
});
}
swal({
title: "Great!",
text: "We have received your request",
type: "success",
timer: 3000,
confirmButtonText: "Wohoo!"
});
clear();
};
var clear = function(){
$scope.application = {
technical: false,
business: false
};
};
//Universities
$scope.application.selectname1={id:100,name: 'None'};
$scope.application.selectname2={id:100,name: 'None'};
$scope.application.selectname3={id:100,name: 'None'};
$scope.filter1 = function(item){
return (!($scope.application.selectname1&&$scope.application.selectname1.id)||item.id !=$scope.application.selectname1.id||item.id==100);
};
$scope.filter2 = function(item){
return (!($scope.application.selectname2&&$scope.application.selectname2.id)||item.id!=$scope.application.selectname2.id||item.id==100);
};
$scope.filter3 = function(item){
return (!($scope.application.selectname3&&$scope.application.selectname3.id)||item.id !=$scope.application.selectname3.id||item.id==100);
};
$scope.universities = [
{
id:1,
name: 'IITs'
},
{
id:2,
name: 'IIITs'
},
{
id:3,
name: 'BITS'
},
{
id:4,
name: 'IISc'
},
{
id:100,
name: 'None'
}
];
//Degrees
$scope.application.selectdegree1={id:100,name: 'None'};
$scope.application.selectdegree2={id:100,name: 'None'};
$scope.application.selectdegree3={id:100,name: 'None'};
$scope.filterDegree1 = function(item){
return (!($scope.application.selectdegree1&&$scope.application.selectdegree1.id)||item.id !=$scope.application.selectdegree1.id||item.id==100);
};
$scope.filterDegree2 = function(item){
return (!($scope.application.selectdegree2&&$scope.application.selectdegree2.id)||item.id!=$scope.application.selectdegree2.id||item.id==100);
};
$scope.filterDegree3 = function(item){
return (!($scope.application.selectdegree3&&$scope.application.selectdegree3.id)||item.id !=$scope.application.selectdegree3.id||item.id==100);
};
$scope.degrees = [
{
id:1,
name: 'PhD'
},
{
id:2,
name: 'Masters'
},
{
id:3,
name: 'BTech'
},
{
id:100,
name: 'None'
}
];
$scope.pageChanged = function() {
//alert('Page changed to: ' + $scope.pagination.currentPage);
//$scope.pagination.currentPage = page;
var begin = (($scope.pagination.currentPage - 1) * $scope.numPerPage);
//var end = begin + $scope.numPerPage;
$scope.getPatents(begin)
};
}]);
})();
#Tarun exactly like you said, your structures are the problem, you should have your navbar navigation in a parent/abstract state, the dashboard and other pages in sub states, so in the app.html would be the navbar and remember to include a <div ui-view></div> tag for the contents of dashboard.html to be displayed nested in the app.html parent state once you navigate to /dashboard:
$stateProvider
.state('login', {
url: "/login",
templateUrl: 'pages/login.html',
controller: 'LoginController',
data: {
requireLogin: false
}
})
.state('app', {
abstract: true,
url: '/app',
templateUrl: 'views/app.html',
data: {
requireLogin: true
}
})
.state('app.dashboard', {
url: '/dashboard',
controller: 'DashboardCtrl',
templateUrl: 'pages/map.html',
data: {
requireLogin: true
}
});
This is my main HTML file.
<div ng-controller="filterController">
<div class="quick-view" id="quickview" data-toggle="modal" data-target="#modal-bar"
ng-click="quickView(quickview)"><i class="fa fa-eye">
</i><span>Quick View</span></div>
</div>
This is my controller.js file
angular.module('myApp',[]).controller('filterController', function($scope) {
$scope.quickView = function quickView(id){
$.ajax({
type: 'GET',
url: 'assets/external/_modal.html',
data: id,
success: function (data) {
// Create HTML element with loaded data
$('body').append(data);
console.log('body append');
},
error:function(jqXHR,textStatus,exception){console.log('Exception:'+exception);}
});
}
$scope.venue = "India";
}
This is _modal.html
<div ng-controller="filterController">
<p>Hi. I live in {{venue}}</p>
</div>
How can I pass the controller scope to the external file _modal.html so that "I live in India" gets displayed instead of "I live in {{venue}}"?
Try angularjs way. Use uib modal. https://angular-ui.github.io/bootstrap
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope,$uibModal, $log, $document) {
$scope.animationsEnabled = true;
$scope.Venue = "India"; // declare venue
$scope.open = function (size, parentSelector) {
var parentElem = parentSelector ?
angular.element($document[0].querySelector('.modal-demo ' + parentSelector)) : undefined;
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
appendTo: parentElem,
resolve: {
values: function () {
return $scope.Venue; //we are passing venue as values
}
}
});
modalInstance.result.then(function () {
$scope.msg = "Submitted";
$scope.suc = true;
}, function(error) {
$scope.msg = 'Cancelled';
$scope.suc = false;
});
};
});
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope,$uibModalInstance, values) { // inject that resolved values
$scope.Venue= values; // we are getting & initialize venue from values
$scope.ok = function () {
$uibModalInstance.close('ok');
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="ModalDemoCtrl" class="modal-demo">
<br>
<form name="form" novalidate>
Type your venue : <input type="text" style="width:200px" class="form-control" name="name" ng-model="Venue" required><br>
<button type="button" ng-disabled="form.$invalid" class="btn btn-default" ng-click="form.$valid && open()">See Venue</button>
</form><br>
<p ng-hide="!msg" class="alert" ng-class="{'alert-success':suc, 'alert-danger':!suc}">{{msg}}</p>
</div>
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Your Details</h3>
</div>
<div class="modal-body" id="modal-body">
<p>The venue is <b>{{Venue }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok()">Submit</button>
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
</body>
</html>
I'm learning how to use Angularjs with ROR through this tutorial https://thinkster.io/angulartutorial/angular-rails/
I've come to a point where when I'm adding a new function for a service which is supposed to get all posts we have in the db. However When I run the code the page does not load anymore. Or at least the html is not rendered. There is no indication of errors in the elements inspections. However I'm not sure it has to do with the placing of the function in the js file. I'm totally new to js and I still struggle to read the sintax and spot errors in the code. Rubymine has given a clue with and Unreacheble code warning for the o.getAll. If someone could have a look at it and give me any hints it would be great.
Apologies to all the code in one file both html and js. I'm having some issues with the assets pipeline that I mean to get fixed soon.
app.js
Blockquote
angular.module('flapperNews', ['ui.router'])
//Provider
.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'MainCtrl',
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
})
.state('posts', {
url: '/posts/{id}',
templateUrl: '/posts.html',
controller: 'PostsCtrl'
})
$urlRouterProvider.otherwise('home');
}])
//Posts service
.factory('posts', ['$http', function($http){
var o = {
posts: []
};
return o;
o.getAll = function() {
return $http.get('/posts.json').success(function(data){
angular.copy(data, o.posts);
});
};
}])
//Main Controller
.controller('MainCtrl', [
'$scope',
'posts',
function($scope, posts){
$scope.posts = posts.posts;
$scope.addPost = function(){
if(!$scope.title || $scope.title == '') { return; }
$scope.posts.push({
title: $scope.title,
link: $scope.link,
upvotes: 0,
comments: [
{author: 'Joe', body: 'Cool post!', upvotes: 0},
{author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0}
]
});
$scope.title = '';
$scope.link = '';
};
$scope.incrementUpvotes = function(post) {
post.upvotes += 1;
};
}])
//Posts Controller
.controller('PostsCtrl', [
'$scope',
'$stateParams',
'posts',
function($scope, $stateParams, posts){
$scope.post = posts.posts[$stateParams.id];
$scope.addComment = function(){
if($scope.body === '') { return; }
$scope.post.comments.push({
body: $scope.body,
author: 'user',
upvotes: 0
});
$scope.body = '';
};}]);
>
and following the application.html.erb
> Blockquote
<html>
<head>
<title>FlapperNews</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="javascripts/app.js"></script>
<script src="javascripts/application.js"></script>
<%= csrf_meta_tags %>
</head>
<body ng-app="flapperNews">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<ui-view></ui-view>
</div>
</div>
<script type="text/ng-template" id="/home.html">
<div class="page-header">
<h1>Flapper News</h1>
</div>
<div ng-repeat="post in posts | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up"
ng-click="incrementUpvotes(post)"></span>
{{post.upvotes}}
<span style="font-size:20px; margin-left:10px;">
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</span>
<span>
Comments
</span>
</div>
<form ng-submit="addPost()"
style="margin-top:30px;">
<h3>Add a new post</h3>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Title"
ng-model="title">
</div>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Link"
ng-model="link">
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>
</script>
<script type="text/ng-template" id="/posts.html">
<div class="page-header">
<h3>
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</h3>
</div>
<div ng-repeat="comment in post.comments | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up"
ng-click="incrementUpvotes(comment)"></span>
{{comment.upvotes}} - by {{comment.author}}
<span style="font-size:20px; margin-left:10px;">
{{comment.body}}
</span>
</div>
<form ng-submit="addComment()"
style="margin-top:30px;">
<h3>Add a new comment</h3>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Comment"
ng-model="body">
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>
</script>
</body>
</html>
From factory you are returning o before the getAll function so it is unreachable
.factory('posts', ['$http', function($http){
var o = {
posts: []
};
//removed return
o.getAll = function() {
return $http.get('/posts.json').success(function(data){
angular.copy(data, o.posts);
});
};
return o; //at the added return
}])
I am new to AngularJs and for stackoverflow too,hope will get a solution for my problem here. I`m trying to display the details of an experiment(in the same page)based on the name of the experiment which is coming from the URL when the name is clicked(index.html). Here the problem is,when I click an experiment name,it is coming in the URL but not able to fetch its details.Can anyone help me to solve.Here is my code.
//experiments.json
[
{
"sl_no" : "1",
"name" : "BCD adders",
"objective" : "It deals with the desinging of reversible BCD adders."
},
{"sl_no" : "2",
"name" : "Online Banking",
"objective" : "It deals with the online Transactions."}
]
//index.html
<!DOCTYPE html>
<html ng-app="experimentApp">
<head>
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js"></script>
<script src="js/controller.js"></script>
</head>
<body>
<div id="main">
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">Angular Routing Example</a>
</div>
<br>
<ul class="nav navbar-nav navbar-left">
<div>
<ul ng-controller="ExperimentListCtrl">
<li ng-repeat="experiment in experiments">
<a href="#/{{experiment.name | encodeURI}}">
<strong>{{experiment.sl_no}}. {{experiment.name}}</strong><br>
</a>
</li>
</ul>
<div ng-include="experiment-detail.html"></div>
</div>
</ul>
</div>
</nav>
</div>
</body>
</html>
//controller.js
// create the module and name it experimentApp
var experimentApp = angular.module('experimentApp', ['ngRoute']);
// configure our routes
experimentApp.config(function($routeProvider) {
$routeProvider.
when('/:experimentName', {
templateUrl : 'experiment-detail.html',
controller : 'ExperimentDetailCtrl'
}).
otherwise({
redirectTo: '/'
});
});
experimentApp.factory('experiments', function($http){
function getData(callback){
$http({
method: 'GET',
url: 'experiments.json',
cache: true
}).success(callback);
}
return {
list: getData,
find: function(name, callback){
getData(function(data) {
var experiment= data.filter(function(entry){
return entry.name === name;
})[0];
callback(experiment);
});
}
};
});
experimentApp.controller('ExperimentListCtrl', function ($scope, experiments){
experiments.list(function(experiments) {
$scope.experiments = experiments;
});
});
experimentApp.controller('ExperimentDetailCtrl', function ($scope, $routeParams,
experiments){
experiments.find($routeParams.experimentName, function(experiment) {
$scope.experiment = experiment;
});
});
experimentApp.filter('encodeURI', function(){
return window.encodeURI;
});
//experiment-detail.html
<div>
<strong>{{experiment.sl_no}}. {{experiment.name}}</strong><br>
</br></br>
<strong>Aim :</strong>{{experiment.objective}}
</div>
You need to encode the experiment.name only, so change :
experimentApp.filter('encodeURI', function(){
return window.encodeURI;
});
to :
experimentApp.filter('encodeURI', function(stringToEncode){
return encodeUri(stringToEncode);
});