Javascript AngularJS:带有查询字符串和表单的单页应用程序?
AngularJS的目标是SPA(单页应用程序)开发,这是常识。尽管如此,也可以创建MPA(多页应用程序) 我的应用程序基于多个状态,使用角度库,如Javascript AngularJS:带有查询字符串和表单的单页应用程序?,javascript,html,angularjs,model-view-controller,angular-ui-router,Javascript,Html,Angularjs,Model View Controller,Angular Ui Router,AngularJS的目标是SPA(单页应用程序)开发,这是常识。尽管如此,也可以创建MPA(多页应用程序) 我的应用程序基于多个状态,使用角度库,如ui-router和ngResource。首先,我有一个index.html文件,在其中加载所有依赖项和一个ui视图。然后我有三个不同的模块:一个主要模块包含顶级状态、第一个主页并加载所有需要的第三方模块。另一个模块名为Student,它有一个简单的表单,可以在Django后端发布一些数据 问题在于第三个模块:公司模块。这里我们有两个导航栏:一个顶部
ui-router
和ngResource
。首先,我有一个index.html
文件,在其中加载所有依赖项和一个ui视图
。然后我有三个不同的模块:一个主要模块包含顶级状态、第一个主页并加载所有需要的第三方模块。另一个模块名为Student,它有一个简单的表单,可以在Django后端发布一些数据
问题在于第三个模块:公司模块。这里我们有两个导航栏:一个顶部导航栏,目前没有任何内容,然后是一个包含多个按钮的侧栏,如图所示:
现在,侧边栏上的每个按钮都会将用户带到不同的状态,其中视图加载到可以看到“欢迎…”的空间中
基本上,我们的州是这样定义的:
'use strict';
talentforce_company
.config(['$stateProvider', '$urlRouterProvider', 'eehNavigationProvider',
function($stateProvider, $urlRouterProvider, eehNavigationProvider) {
// Company area states
$stateProvider.state('companyState', {
url: '/company',
abstract: true,
//redirectTo: 'homeState',
template: '<company-area-directive></company-area-directive>'
});
$stateProvider.state('homeState', {
url: '/home',
parent: 'companyState',
controller: ['$scope', '$rootScope', function($scope, $rootScope) {
$rootScope.name_filter = "";
$rootScope.city_filter = "";
}
],
template: '<h3>Welcome to TalentForce company area home</h3>'
});
$stateProvider.state('select_study_areas', {
url: '/select_areas',
parent: 'companyState',
template: '<study-areas-directive></study-areas-directive>'
});
$stateProvider.state('TalentForceState_seeProfile', {
url: '/profile_list',
parent: 'companyState',
// controller: 'People_Controller',
template: '<people-directive></people-directive>',
});
$stateProvider.state('student', {
url: '/profile/{personId}',
parent: 'companyState',
//templateUrl: 'public/templates/person_template.html',
controller: 'Person_Controller',
template: '<profile-directive></profile-directive>',
resolve: {
student: function(student_service, $stateParams) {
return student_service.getStudents().find(function(student) {
return (student.student_id == $stateParams.personId);
});
}
}
});
eehNavigationProvider
.menuItem('TF_menu_top.users', {
text: 'USERNAME',
iconClass: 'glyphicon-user',
href: '#'
});
eehNavigationProvider
.menuItem('TF_sidebar.home', {
text: 'Home',
state: 'homeState',
iconClass: 'fa fa-home fa-fw',
})
.menuItem('TF_sidebar.profile', {
text: 'Company Profile',
href: '#',
iconClass: 'fa fa-building fa-fw'
})
.menuItem('TF_sidebar.students', {
text: 'Profiles',
state: 'select_study_areas',
//href: '/select_areas',
iconClass: 'fa fa-users fa-fw'
})
.menuItem('TF_sidebar.posts', {
text: 'Job Posts',
href: '#',
iconClass: 'fa fa-list-alt fa-fw'
})
.menuItem('TF_sidebar.stats', {
text: 'Statistics',
href: '#',
iconClass:'fa fa-bar-chart fa-fw'
})
.menuItem('TF_sidebar.universities', {
text: 'Universities',
href: '#',
iconClass:'fa fa-university fa-fw'
})
.menuItem('TF_sidebar.tips', {
text: 'Tips',
href: '#',
iconClass: 'fa fa-check-square-o fa-fw'
})
.menuItem('TF_sidebar.events', {
text: 'Events',
href: '#',
iconClass: 'fa fa-calendar fa-fw'
})
.menuItem('TF_sidebar.help', {
text: 'Help',
href: '#',
iconClass: 'fa fa-question fa-fw'
})
}]);
$http.get("http(s)://serverurl.com/api/endpoint?color=red&sort=ascending&sortBy=name").then(function(resp){
//handle response as you want
//you can go to next state via $state.go("stateB", {params: resp.data}) and render view according to the new data
});
我们的想法是在每次更新过滤器时重新加载结果(因此,在URL中重新加载带有查询字符串的页面)
请注意,我们使用name
属性,以便在控制器中执行以下操作:
var queryString = $('#myFormId').serialize();
当我们在控制台中打印queryString
时,它实际上构造得很好:country=pt&student\u city=Montijo%2C+葡萄牙
但是我不知道在哪里以及如何使用这个字符串。我应该使用JSON文件吗?如何在Angular应用程序中进行动态过滤?我是否需要改变我的架构,或者更糟糕的是,改变框架
我担心通过使用所有这些状态和路由,我不能使用这种类型的过滤器。关于如何实现这一点有什么想法吗?我在互联网上找不到任何教程,最接近我的是因为它实际上解释了一个与我类似的问题,但我试图模仿这个解决方案,但什么也没发生 如果我很了解您的问题,那么您希望将数据从一个州发送到另一个州。ui路由器中有
$stateParams
服务解决了这个问题。你可以在这里找到关于它的文档
因此,您有一个状态A,您可以在其中选择一些过滤器。要使用绑定,很容易从用户那里收集信息。因此,您将有一些对象,如:
{
color: red,
sort: ascending,
sortBy: name
}
您可以通过$http创建AJAX请求,从服务器获取数据,如下所示:
'use strict';
talentforce_company
.config(['$stateProvider', '$urlRouterProvider', 'eehNavigationProvider',
function($stateProvider, $urlRouterProvider, eehNavigationProvider) {
// Company area states
$stateProvider.state('companyState', {
url: '/company',
abstract: true,
//redirectTo: 'homeState',
template: '<company-area-directive></company-area-directive>'
});
$stateProvider.state('homeState', {
url: '/home',
parent: 'companyState',
controller: ['$scope', '$rootScope', function($scope, $rootScope) {
$rootScope.name_filter = "";
$rootScope.city_filter = "";
}
],
template: '<h3>Welcome to TalentForce company area home</h3>'
});
$stateProvider.state('select_study_areas', {
url: '/select_areas',
parent: 'companyState',
template: '<study-areas-directive></study-areas-directive>'
});
$stateProvider.state('TalentForceState_seeProfile', {
url: '/profile_list',
parent: 'companyState',
// controller: 'People_Controller',
template: '<people-directive></people-directive>',
});
$stateProvider.state('student', {
url: '/profile/{personId}',
parent: 'companyState',
//templateUrl: 'public/templates/person_template.html',
controller: 'Person_Controller',
template: '<profile-directive></profile-directive>',
resolve: {
student: function(student_service, $stateParams) {
return student_service.getStudents().find(function(student) {
return (student.student_id == $stateParams.personId);
});
}
}
});
eehNavigationProvider
.menuItem('TF_menu_top.users', {
text: 'USERNAME',
iconClass: 'glyphicon-user',
href: '#'
});
eehNavigationProvider
.menuItem('TF_sidebar.home', {
text: 'Home',
state: 'homeState',
iconClass: 'fa fa-home fa-fw',
})
.menuItem('TF_sidebar.profile', {
text: 'Company Profile',
href: '#',
iconClass: 'fa fa-building fa-fw'
})
.menuItem('TF_sidebar.students', {
text: 'Profiles',
state: 'select_study_areas',
//href: '/select_areas',
iconClass: 'fa fa-users fa-fw'
})
.menuItem('TF_sidebar.posts', {
text: 'Job Posts',
href: '#',
iconClass: 'fa fa-list-alt fa-fw'
})
.menuItem('TF_sidebar.stats', {
text: 'Statistics',
href: '#',
iconClass:'fa fa-bar-chart fa-fw'
})
.menuItem('TF_sidebar.universities', {
text: 'Universities',
href: '#',
iconClass:'fa fa-university fa-fw'
})
.menuItem('TF_sidebar.tips', {
text: 'Tips',
href: '#',
iconClass: 'fa fa-check-square-o fa-fw'
})
.menuItem('TF_sidebar.events', {
text: 'Events',
href: '#',
iconClass: 'fa fa-calendar fa-fw'
})
.menuItem('TF_sidebar.help', {
text: 'Help',
href: '#',
iconClass: 'fa fa-question fa-fw'
})
}]);
$http.get("http(s)://serverurl.com/api/endpoint?color=red&sort=ascending&sortBy=name").then(function(resp){
//handle response as you want
//you can go to next state via $state.go("stateB", {params: resp.data}) and render view according to the new data
});
在状态B中,您将拥有一些控制器,并且您将使用$stateParams
获取您在状态A上请求的新数据
我提供了另一个例子,我认为它演示了如何工作:
国家的定义:
{
name: 'people',
url: '/people',
resolve: {
people: function(PeopleService) {
return PeopleService.getAllPeople();
}
}
},
{
name: 'people.person',
url: '?isActive&eyeColor',
resolve: {
filteredPeople: function(people, $stateParams) {
var res = [];
people.find(function(person) {
if(shouldWeAddToFiltered($stateParams))
{
res.push(person);
}
});
return res;
}
},
controller: function(filteredPeople){
//do something with filteredPeople array
}
}
在这种情况下,您的url将被更新。因此用户可以将页面添加到书签中。问题是,在过滤的情况下,我不想在状态之间传递数据,这实际上是使用查询字符串向我的服务器进行的查询。然后用收到的信息加载页面。所以你有一些复选框,用户可以选择其中的一些,然后你用这些选择的数据创建一个reguest POST或其他东西到服务器上。这将过滤数据并在新页面(或状态?)上返回人员列表。然后,我还有其他过滤器,如城市、技能等。我想创建一个显示在URL上的查询字符串,以便直接查询数据库,然后用新数据重新加载页面。我已经更新了答案。这是某种伪代码。我只是想提出我如何解决这个问题的想法。我已经在做了。但这些更改不会传播到Angular应用程序的URL。用我在问题中链接的教程中的一句话来说,问题是:“但是如果你想用某种方式记录页面的状态呢?比如说你的用户想为一组过滤器添加书签,或者通过电子邮件将链接发送给他们的同事?”你看到了吗?实际上,无法在URL中指定/序列化筛选器