I am trying to create a new app router within a 'Products' module as shown below using marionette
#MyApp.module "ProductsModule", (ProductsModule, App, Backbone, Marionette, $, _) ->
class ProductsModule.Router extends Marionette.AppRouter
appRoutes:
"products" : "listGoods"
API =
listGoods: ->
console.log('list goods')
App.addInitializer ->
console.log('init app router')
new ProductsModule.Router
controller: API
The higher level App code is as follows
#MyApp = do (Backbone, Marionette) ->
App = new Marionette.Application
App.addRegions
headerRegion: "#header-region"
mainRegion: "#main-region"
footerRegion: "#footer-region"
App.on "initialize:after", (options) ->
if Backbone.history
Backbone.history.start
root: '/admin/'
App
However after trying to run, the appRouter for Products Module did not run i.e. console.log did not print out anything to the console.
Am I missing something here?
UPDATE:
Adding more code to show where the app was started
<!DOCTYPE html>
<html>
<head>
<title>Admin</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "admin" %>
<%= csrf_meta_tags %>
</head>
<body>
<div id="wrap">
<div id="header-region"></div>
<div id="main-region" class="container">
sss
</div>
</div>
<div id="footer-region"></div>
//STARTING APP HERE
<%= javascript_tag do %>
$(function() {
MyApp.start();
});
<% end %>
</body>
</html>
Move
console.log('init app router')
new ProductsModule.Router
controller: API
in
App.on("initialize:after", function(){/*place code here*/})
Move
if Backbone.history
Backbone.history.start
root: '/admin/'
in
App.on("start", function(){/*place code here*/})
Related
I'm trying to make a foreign language chat app (because I love languages) that is similar to Omegle.com!
I'm making my chat application using PubNub and AngularJS.
Basically, my chat app is designed like this:
First the user is presented with a screen of what language they can speak and what language they want to learn
Let's say I am an English speaker and I am learning German (HomeController)
They press the CHAT! button and goes to my ChatController
From here, the user is in a queue until a native speaker match to their learning language is found (this is the part where I'm having the most trouble)
Here are pictures to get a better idea: http://imgur.com/a/1yGST
Here is what I have so far:
index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Linga!</title>
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="css/reset.css" />
<link rel="stylesheet" type="text/css" href="css/semantic.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css" />
<!-- AngularJS and jQuery -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="https://code.angularjs.org/1.2.28/angular-route.min.js"></script>
<script
src="http://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous">
</script>
<!-- PubNub Service -->
<script src="http://cdn.pubnub.com/pubnub.min.js"></script>
<script src="https://cdn.pubnub.com/sdk/pubnub-angular/pubnub-angular-4.0.2.min.js"></script>
<!-- Underscore support -->
<script src="js/vendor/underscore-min.js"></script>
<!-- Scroll Glue -->
<script src="https://cdn.rawgit.com/Luegg/angularjs-scroll-glue/master/src/scrollglue.js"></script>
<!-- Semantic UI JS -->
<script src="js/vendor/semantic.min.js"></script>
</head>
<body ng-app="ChatApp">
<div ng-view></div>
<!-- App -->
<script src="js/app.js"></script>
<!-- Controllers -->
<script src="js/controllers/HomeController.js"></script>
<script src="js/controllers/ChatController.js"></script>
</body>
</html>
I'm using ng-view to route between my HomeController.js and ChatController.js.
home.html View
<div id="background"></div>
<div class="main">
<div class="ui container">
<div class="ui center aligned segment glass">
<h1 id="linga">Ling<span>a</span></h1>
<form class="ui form" ng-submit="submit()" name="chatForm">
<div class="field">
<label>I speak</label>
<select class="ui fluid dropdown" ng-model="selectedNative" ng-options="language.name for language in languages">
<option value="">Language</option>
</select>
</div>
<div class="field">
<label>Find someone</label>
<select class="ui fluid dropdown" ng-model="selectedLearning" ng-options="language.name for language in languages">
<option value="">Language</option>
</select>
</div>
<button class="ui button" id="submit" type="submit">CHAT</button>
</form>
</div>
</div>
</div>
Here the user selects what language they are native in and what they are learning. And then the chat button is pressed which goes to the submit() function in my HomeController.js.
HomeController.js
app.controller('HomeController', ['$scope', '$location', 'languageService', function($scope, $location, languageService){
//$scope.hello = "hi!";
$scope.languages = [
{
name:'German',
flag:'img/flags/de.png'
},
{
name:'French',
flag:'img/flags/fr.png'
},
{
name:'English',
flag:'img/flags/us.png'
},
{
name:'Portuguese',
flag:'img/flags/br.png'
},
{
name:'Persian',
flag:'img/flags/ir.png'
},
{
name:'Russian',
flag:'img/flags/ru.png'
},
{
name:'Swedish',
flag:'img/flags/se.png'
},
{
name:'Turkish',
flag:'img/flags/tr.png'
},
{
name:'Spanish',
flag:'img/flags/es.png'
},
{
name:'Italian',
flag:'img/flags/it.png'
}
];
$scope.submit = function(){
languageService.setNative($scope.selectedNative.name);
languageService.setLearning($scope.selectedLearning.name);
$location.path("/chat");
}
}]);
$(document).ready(function(){
$('.ui.dropdown').dropdown();
});
Here the submit() function in my HomeController.js puts the native and learning language information in my languageService so that my ChatController.js can use the information.
app.js
var app = angular.module('ChatApp', ['ngRoute', 'pubnub.angular.service', 'luegg.directives']);
app.service('languageService', function(){
var languages = {
nativeLanguage: '',
learningLanguage: ''
};
return{
setNative: setNative,
setLearning: setLearning,
getLanguages: getLanguages
};
function getLanguages(){
return languages;
};
function setNative(nativeLanguage){
languages.nativeLanguage = nativeLanguage;
};
function setLearning(learningLanguage){
languages.learningLanguage = learningLanguage;
};
});
app.config(function($routeProvider, $locationProvider){
$routeProvider
.when('/', {
controller:'HomeController',
templateUrl:'views/home.html'
})
.when('/chat', {
controller:'ChatController',
templateUrl:'views/chat.html'
})
.otherwise({
redirectTo: '/'
});
});
app.directive('ngEnter', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 13) {
scope.$apply(function (){
scope.$eval(attrs.ngEnter);
});
event.preventDefault();
}
});
};
});
This service in app.js puts the information attained from HomeController.js and makes them available for controllers.
ChatController.js
app.controller('ChatController', ['$scope', '$rootScope', 'languageService', 'Pubnub',
function($scope, $rootScope, languageService, Pubnub){
$scope.languages = languageService.getLanguages();
$scope.channel = 'messages-channel';
// Generating a random uuid between 1 and 100 using an utility function from the lodash library.
$scope.uuid = _.random(100).toString();
Pubnub.init({
publish_key: 'demo',
subscribe_key: 'demo',
uuid: $scope.uuid
});
// Send the messages over PubNub Network
$scope.sendMessage = function() {
// Don't send an empty message
if (!$scope.messageContent || $scope.messageContent === '') {
return;
}
Pubnub.publish({
message: {
content: $scope.messageContent,
sender_uuid: $scope.uuid,
date: new Date()
},
channel: $scope.channel
});
// Reset the messageContent input
$scope.messageContent = '';
}
$scope.messages = [];
// Subscribing to the ‘messages-channel’ and trigering the message callback
Pubnub.subscribe({
channel: $scope.channel,
withPresence: true,
triggerEvents: ['callback']
});
// Listening to the callbacks
$rootScope.$on(Pubnub.getMessageEventNameFor($scope.channel), function(ngEvent, m){
$scope.$apply(function(){
$scope.messages.push(m);
});
});
}]);
chat.html View
<div class="main-chat">
<div class="ui container">
<div class="chat-box ui segment" id="style-3" scroll-glue>
<p>Searching for a {{languages.learningLanguage}} speaker ...</p>
<ul>
<li ng-repeat="message in messages">
<strong>Anonymous {{message.sender_uuid}}: </strong>
<span>{{message.content}}</span>
</li>
</ul>
</div>
<div class="chat-field ui segement">
<div class="ui form">
<textarea ng-enter="sendMessage()" ng-model="messageContent"></textarea>
</div>
</div>
</div>
</div>
And so here's where I'm stuck. For example, if I'm learning German, I want my chat app to stay in queue until a German native is found using the variables I made in my languageService. When it is found, they go into the chat and start learning languages!
My logic:
Need to find out who's currently using my app (for example 1,000 people)
Then I search in some sort of array for a native speaker I want to learn with
The most immediate match will terminate the loop (or listener) and go straight into chat
I did try adding Pubnub.addListener to my ChatController.js but it says that Pubnub.addListener is not a function error.
Tackled this problem for many hours reading a lot of tutorials on PubNub, but I can't figure it out at all.
Thank you so much for your help. I tried to make it as clear as possible.
First, addListener not a function must mean that PubNub object is out of scope (it must be) but don't have further insight at this time.
For your list of available native speakers, just create a channel for each language: native.german, native.french, etc. As users logon, have them subscribe to the proper native.<lang> channel.
You can use hereNow to get the list of active/online native speakers for that language.
And use PubNub Functions to do the translation in realtime without hitting your server to do that work.
I have an inquiry about the failure of ng-view to render a partial view in a cshtml page in a hybrid angularjs and asp.net mvc application. I have seen this work before, but cannot locate the cause of my failure.
the general scenario is to present a cshtml page which accepts input for a search and present the results on the same page while retaining the input text box for subsequent searches.
the cshtml page:
#{
ViewBag.Title = "Search";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Search</title>
<base href="/" />
</head>
<body>
<div data-ng-app="searchModule" data-ng-controller="searchController">
<br />
<form id="search-form" data-ng-submit="searchProperty()" >
<label for="search" data-icon="">
<input id="search" type="search" data-ng-model="searchTerm" placeholder="enter title of property to find" style="width:800px; max-width:800px" />
</label>
</form>
</div>
<div>
<div ng-view="">
</div>
</div>
</body>
</html>
#section Scripts {
#Scripts.Render("~/bundles/searchBundle")
}
the angularjs controller responding to the search string submission:
searchModule.controller('searchController', function ($scope, $location, $window) {
var url = "/search/results/";
$scope.searchProperty = function()
{
//$location.path(url + $scope.searchTerm);
window.location = url + $scope.searchTerm;
}
});
searchModule.controller('searchResultsController', function($scope, $routeParams) {
$scope.searchTerm = 'test';
$scope.properties = [];
$scope.properties.push( {"id" : "1", "title": "property"});
});
the angularjs router which should handle the injection into the cshtml:
var searchModule = angular.module('searchModule', ['ngRoute']);
searchModule.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/search/results/:searchterm',
{
templateUrl: function (params) { return '/search/results/' + params.searchterm; },
controller: 'searchResultsController', //angularjs controller; the templateUrl is an mvc reference.
})
//.otherwise({ redirectTo: '/' });
$locationProvider.html5Mode(true);
});
the relevant section of the mvc controller:
public class SearchController : Controller
{
// GET: Search
public ActionResult Index()
{
return View();
}
// GET: Search/Results/"title"
[Route("Search/Results/{SearchTerm}")]
public ActionResult Results(string SearchTerm)
{
return PartialView();
}
finally, the cshtml partial view rendering the search results. I expected this to be injected into the index.cshtml, but is actually rendered on a new page.
#{
ViewBag.Title = "Search Results";
}
<div>
<br />
<h3 class="keyword" data-ng-show="searchTerm != null">Search: {{searchTerm}}</h3>
<table>
<tbody>
<tr data-ng-repeat="property in properties">
<td>{{property.id}}</td>
<td>{{property.title}}</td>
<td><a data-ng-href="/details/{{property.id}}" data-icon="→"></a></td>
</tr>
</tbody>
</table>
</div>
the following url appears when landing on the search box page:
http://localhost:5240/Search
the following url appears after the submission on a blank page except for the bad angularjs markup which can't find the desired scope.
http://localhost:5240/search/results/333
these are both good and desirable.
I am trying to avoid having the dreaded # appear in the url.
My problem was due to lack of recognizing the true root of the navigation tree.
When I changed the navigation url as follows, the application worked as desired.
var url = "/search/#/results"; //good url
var url = "/search/results/"; //bad url
the key was that the search box page is navigated to from a main page, and is part of a spa farm, so extra attention is needed for managing navigation trees.
I am still unhappy with the hash in the url, but will address that matter as a separate query when I undertake to better understand $locationProvider.html5Mode(true);
I have simple Scala Play Framework and Angular application. I tried to render JSON data on play's "xxx.scala.html" template but don't know what is the problem it is not rendering as expeted.
#main("Welcome to Play") {
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"> </script>
<script>
app.controller('NamesCtrl', function($scope) {
// get names using AngularJS AJAX API
$http.get('/getNames').success(function(data){
$scope.names = data;
});
});
</script>
<div ng-app="app" ng-contoller="NamesCtrl">
<ul>
<li ng-repeat=" name in names">{{name}}</li>
</ul>
</div>
}
My route entry
GET /getNames controllers.HomeController.getNames
Scala Controller:
def getNames = Action {
val names = List("Bob","Mike","John")
Ok(Json.toJson(names)).as(JSON)
}
When I am calling my page using url
http://localhost:9000/getNames
I was getting response on page as below,
["Bob","Mike","John"]
Please can you explain what am I doing wrong here?
Thanks !!
There are some problems in the code. The correct one is this:
#main("Welcome to Play") {
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.19/angular.min.js"></script>
<div ng-app="myApp" ng-controller="NamesCtrl">
<ul>
<li ng-repeat="name in names">{{name}}</li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('NamesCtrl', function($scope, $http) {
$http.get('/getNames').success(function(data){
console.log(data);
$scope.names = data;
});
});
</script>
}
What has changed:
AngularJS 1.3.19 instead of 1.2.10
AngularJS module - which is referenced in the div
injected the $http service in the controller
your ng was wrong - it should be ng-controller instead of ng-contoller (a typo I guess)
The result is what you would expect:
I'm trying to add the wysiwyg nicEdit text editor to my text areas. When I goto the actual templateUrl the textbox and tool bar do work but they do not submit correctly (to my firebase db). When I goto the page that is to render the template I am unable to get get nicEdit toolbar features and just get a regular text area box. I'm using angularjs and have the templateurl as addPost.html.
So again the template does render when I goto #/addPost but not with the working nicEdit features, yet going directly to the template url addPost.html does have the nicEdit features working but then won't submit to my firebase db. Anyone have an idea on why this is so? Thanks.
Template file addPost.html:
<head>
<script type="text/javascript" language="javascript" src="../nicEdit.js"></script>
<script type="text/javascript" language="javascript">
bkLib.onDomLoaded(nicEditors.allTextAreas);
</script>
<!-- Bootstrap core CSS -->
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<nav class="blog-nav">
<a class="blog-nav-item " href="#/welcome">Home</a>
<a class="blog-nav-item active" href="#/addPost">Add Post</a>
<a class="blog-nav-item " style="cursor:pointer;" ng-click="logout();">Logout</a>
</nav>
</head>
<body ng-controller="AddPostCtrl">
<div class="container" >
<form class="form-horizontal" ng-submit="AddPost()">
<fieldset>
<!-- Form Name -->
<legend>Create Post</legend>
<!-- Textarea -->
<div class="form-group">
<label class="col-md-4 control-label" for="txtPost">Post</label>
<div class="col-md-4">
<textarea class="form-control" id="txtPost" ng-model="article.post" name="txtPost" ></textarea>
</div>
</div>
</fieldset>
</form>
</div><!-- /.container -->
</body>
addPost.js
'use strict';
angular.module('myApp.addPost', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/addPost', {
templateUrl: 'addPost/addPost.html',
controller: 'AddPostCtrl'
});
}])
.controller('AddPostCtrl', ['$scope','$firebase','$location','CommonProp',function($scope,$firebase, $location,CommonProp) {
if(!CommonProp.getUser()){
$location.path('/main');
}
$scope.logout = function(){
CommonProp.logoutUser();
}
$scope.AddPost = function(){
var title = $scope.article.title;
var date = $scope.article.date;
var post = $scope.article.post;
var firebaseObj = new Firebase("http://..");
var fb = $firebase(firebaseObj);
fb.$push({ title: title, date: date, post: post,emailId: CommonProp.getUser() }).then(function(ref) {
console.log(ref);
$location.path('/welcome');
}, function(error) {
console.log("Error:", error);
});
}
}]);
Going to #addPost shows the template with out nicEdit working
But going to the actual templateUrl addPost.html it works fine, minus not being able to submit
The problem has to do with trying to run scripts Angular html partials. The simple solution is to move the scripts you need to the head of your main index file, outside of ng-view, though it does seem (according to other stackoverflow posts) technically possibly to try to get these scripts to execute:
"AngularJS: How to make angular load script inside ng-include?"
https://stackoverflow.com/a/19715343/1078450
(Also, you have html in your head file that is not likely to be rendered: <nav class="blog-nav">)
Well, I have had the same problem, with initialisation of NicEdit in templates.
First I used onDomLoaded() else, but it's better to wait for the document. With jQuery I use document.ready.
Take a look here, pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it
The problem is to tell NicEditor the new textarea.
Here a code sample to do this in jQuery.
var idnr = 0;
var NicEditor = new nicEditor();
$('#add').click(function(){
var $clone = $('#dummy').clone();
var id = 't_' + idnr;
idnr = idnr + 1;
$clone.attr('id',id).attr('name',id).removeClass('dummy');
$('#wrapper').append($clone);
NicEditor.panelInstance(id);
$(nicEditors.findEditor(id).elm).focus();
});
And here is a working Example of dynamic NicEdit use.
I am trying to make a simple project where i want to populate the section with ng-view directive and i keep getting the following error:
I also included in index.html the angular files:
1-angular min js
2-angular-route min js
3-angular-resource min js
Error: $injector:modulerr Module Error Failed to instantiate module
booksInventoryApp due to: Error: [$injector:modulerr]
How can i fix this?
My code is:
index.html
<!DOCTYPE html>
<html ng-app="booksInventoryApp">
<body>
<section ng-view></section>
<script src="js/index.js"></script>
</body>
</html>
index.js
var app = angular.module('booksInventoryApp', ['booksInventoryApp.bsm','booksInventoryApp.allBooks']);
//route provider
app.config(['$routeProvider', function($routeProvider){
$routeProvider
// route for the index page
.when('/', {
templateUrl : '../allBooks.html',
controller : 'booksCtrl'
})
// route for the best selling month page
.when('/bsm/:id', {
templateUrl : 'bsm.html',
controller : 'bsmCtrl'
})
// route for the root
.otherwise({
redirectTo : '/'
});
}]);
bsm.js
var app = angular.module('booksInventoryApp.bsm', []);
app.controller('bsmCtrl', function($scope) {
$scope.book = "Bla Bla";
});
bsm.html
<section class="container">
{{book}}
</section>
allBooks.js
var app = angular.module('booksInventoryApp.allBooks', []);
// controllers
app.controller('booksCtrl', function($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks")
.success(function(data) {
$scope.data = data;
});
});
allBooks.html
<section class="row">
<section class="col-sm-6 col-md-2" ng-repeat="book in data.books">
<section class="thumbnail">
<img ng-src="{{book.url}}">
<section class="caption">
<h3>{{book.name}}</h3>
<p>Author: {{book.author}}</p>
<p>ID: <span class="badge">{{book.id}}</span></p>
<p>Available: <span class="badge">{{book.amount}}</span></p>
<p>Price: <span class="badge">${{book.price}}</span></p>
<p><a ng-src="#/bsm/{{book.id}}"><button class="btn btn-info">Best selling month</button></a></p>
</section>
</section>
</section>
</section>
You need to add ngRoute module in your app and also the script reference of the angular-route.min.js write after the angular.js, Also you need to add bsm.js and allBooks.js in your html after above two mentioned file has loaded.
Code
var app = angular.module('booksInventoryApp', [
'booksInventoryApp.bsm',
'booksInventoryApp.allBooks',
'ngRoute'
]);
Note
Both the version of angular.js & angular.route.js should be the
same otherwise it will show some wierd issue. Preferred version is 1.3.15
In your index.html page you not included bsm.js and allBooks.js files which contains the required dependencies of your app.
Since you have specified the dependency of 'booksInventoryApp.bsm','booksInventoryApp.allBooks' in your app angular is not able to find those modules and hence you are getting that error.
Also you need to include angular route script reference and ngRoute in your dependencies because you are using angular routing in your app.
var app = angular.module('booksInventoryApp', ['ngRoute', 'booksInventoryApp.bsm', 'booksInventoryApp.allBooks']);