Access HTML DOM from Javascript file (Meteor) - javascript

I'm not sure if this is a good question or even a right approach but I'm just wondering how I could possibly disable a button from my JS file using Meteor.
I attempted
$("#button").disabled = true;
And it didn't work. I'm not sure if this is the right approach or not. I thought of maybe creating a function under a script tag in my HTML file but I thought that would seem redundant considering I have a JS file which represents my model so I was just attempting on figuring out if I can access HTML tags from that file.
Here's the code:
Users = new Mongo.Collection("user-info");
if (Meteor.isClient) {
var myApp = angular.module('calorie-counter',['angular-meteor']);
myApp.controller('formCtrl',['$scope',function($scope) {
$("#button").disabled=true;
$scope.calories;
$scope.goal;
$scope.user;
$scope.submit = function() {
Meteor.call("submit",$scope.user);
$scope.clear();
}
$scope.clear = function() {
$scope.user = {
item1:'',
item2:'',
calories:'',
goal:''
};
}
}]);
}

First, I'm not angularjs user.
But your code must to run template render after.
try to change your code like below. (Note: "yourTemplate" change to yours)
Users = new Mongo.Collection("user-info");
if (Meteor.isClient) {
Template.yourTemplate.onRendered(function() {
var myApp = angular.module('calorie-counter', ['angular-meteor']);
myApp.controller('formCtrl', ['$scope',
function($scope) {
$("#button").disabled = true;
$scope.calories;
$scope.goal;
$scope.user;
$scope.submit = function() {
Meteor.call("submit", $scope.user);
$scope.clear();
}
$scope.clear = function() {
$scope.user = {
item1: '',
item2: '',
calories: '',
goal: ''
};
}
}
]);
});
}

Related

How to inject a custom filter in AngularJS 1.6

I have a component into which I would like to inject a custom filter, status.
My component looks like this:
function ClaimsListController(dpClaimsListService) {
var ctrl = this;
ctrl.claims = null;
ctrl.searchCriterion = null;
ctrl.loadClaimsList = function() {
dpClaimsListService.getUploadRequests(1,
function (claims) {
ctrl.claims = claims.data;
},
function () {
// error handling? display message to user?
});
}
ctrl.loadClaimsList(1);
}
angular.module('dpApp').component('dpClaimsListService', {
templateUrl: '/templates/dp-claims-list.tmpl.html',
controller: ClaimsListController
});
I can't work out how to inject my status filter into my component in a DI-minificaiton safe way. Any help appreciated.
Turns out that I don't need to inject the filter; I neglected to include it in my bundle.

Load data from Firebase using AngularJS immediately

I am trying to make a comments section on my website. I have properly linked all my files and getting data from Firebase is working. But, the comments only load after I either click on something or enter text in the "Add comment" field; it does not show the comments instantly when the page loads. Does anyone know why?
Relevant code: (placed at the top of my controller)
$scope.comments = {};
database.ref('comments').on('value', function(items) {
$scope.comments = items.val();
});
$scope.comment = function() {
database.ref('comments').push($scope.newComment);
$scope.newComment = "";
};
Use $scope.$apply
$scope.comments = {};
database.ref('comments').on('value', function(items) {
$scope.$apply(function () {
$scope.comments = items.val();
});
});
$scope.comment = function() {
database.ref('comments').push($scope.newComment);
$scope.newComment = "";
};

How to make an AngularJS scope variable dependent on media query with EnquireJS?

The goal is to make an Angular scope variable dependent on the screen resolution. I found that the EnquireJS library does just that. The final working result should be that the menu collapses when screen is 480px, based on an isCollapsed variable. (I'm using Angular-ui from bootstrap) Note: I must use Angular.
I can attach the Angular scope variable (isCollapsed) to the Javascript $window and address the $window in EnquireJS, this is what I have.
Create module + controller and attach scope + window
angular.module('PremiumMeat', ['ui.bootstrap']);
angular.module('PremiumMeat').controller('CollapseCtrl', function ($scope, $window) {
$scope.isCollapsed = false;
$window.collapsed = false;
});
Enquire setup, initialize variable on false
// Enquire configuration
var enquireQuery= "screen and (max-width:480px)";
var enquireQueryHandler = {
setup: function () {
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=false;
},
The isCollapsed variable should be initialized on false and become true when screen size reaches 480px;
I'm trying to address the variable through the $window and both the document object, but none work.
match: function () {
$scope.isCollapsed = true;
$window.collapsed = true;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=true;
},
unmatch: function () {
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=false;
}
};
Now the question is where to initialize the enquireJS to make it all work.
enquire.register(enquireQuery, enquireQueryHandler, true);
When I put it in the controller it stops working and outside it, it doesn't overrule.
Final working result should be that the menu collapses when screen is 480px. Note: I must use Angular (angular-ui bootstrap)
I created a service to handle EnquireJS media queries in my Angular application that might be of use to you: https://gist.github.com/schuyberg/034a9982bf8326c19fc9
For your case here, the service would look something like this:
services.factory('max480', ['$rootScope', '$timeout', function ($rootScope, $timeout) {
var max480 = {
watch: function() { enquire.register('screen and (max-width: 480px)', max480handler); },
unwatch: function() { enquire.unregister('screen and (max-width: 480px)'); },
ismatch: function(callback) { $rootScope.$on('match480', callback); },
notmatch: function(callback) { $rootScope.$on('unmatch480', callback); },
};
var max480handler = {
match: function() {
$timeout(function(){
$rootScope.$emit('match480');
});
},
unmatch: function(){
$rootScope.$emit('unmatch480');
}
};
return max480;
}]);
Then, inject the service in your controller, and use the following to register the enquire listener, and act on changes:
// this setup can live in your controller
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng controller="CollapseCtrl"]')).scope().isCollapsed=false;
// use the service to listen for, and react to changes
max480.watch();
max480.ismatch(function(){
$scope.isCollapsed = true;
$window.collapsed = true;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=true;
});
max480.notmatch(function(){
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=false;
});
This service has the advantage of being reusable throughout your application. You can also use max480.unwatch(); to unregister the listener if you need to.

How to access a backbone view in another file from backbone router

I have a backbone application which works fine but was getting a bit heavy to be in one file so I have started to separate it into different files I now have:
backbone-view.js
backbone-router.js
...
I am using my backbone router to instantiate views when the URL changes like so:
var Router = Backbone.Router.extend({
routes: {
'our-approach.php': 'instantiateOurApproach',
'our-work.php': 'instantiateOurWork',
'who-we-are.php': 'instantiateWhoWeAre',
'social-stream.php': 'instantiateSocialStream',
'contact.php': 'instantiateContact'
},
instantiateOurApproach: function() {
if(window.our_approach_view == null) {
window.our_approach_view = new OurApproachView();
}
},
instantiateOurWork: function() {
if(window.our_work_view == null) {
window.our_work_view = new OurWorkView();
}
},
instantiateWhoWeAre: function() {
if(window.who_we_are_view == null) {
window.who_we_are_view = new WhoWeAreView();
}
},
instantiateSocialStream: function() {
if(window.social_stream_view == null) {
window.social_stream_view = new SocialStreamView();
}
},
instantiateContact: function() {
if(window.contact_view == null) {
window.contact_view = new ContactView();
}
}
});
The problem I am now having is that I cannot access the views as they are declared in a separate file so the following are all undefined:
OurApproachView()
OurWorkView()
WhoWeAreView()
SocialStreamView()
ContactView()
I have tried doing:
window.OurApproachView()
But this doesn't work.
I am not sure what my next move is so if anyone can help that would be awesome.
Thanks!
EDIT
OK so it seems doing:
window.OurApproachView()
does actually work, my apologies there, but does anyone have a better suggestion?
You can take this approach:
// sample-view.js
var app = app || {};
$(function() {
app.SampleView = Backbone.View.extend({
el: '#sample-element',
template : // your template
events: {
// your events
},
initialize: function() {
// do stuff on initialize
},
render: function() {
// do stuff on render
}
});
});
Similarly, all your js files (models, collections, routers) can be setup like this. You would then be able to access any view from the router by doing:
var view = new app.SampleView();
This works:
window.our_work_view = new window.OurApproachView();
But I don't like it as a solution.
Anyone suggest anything better?

Spine.js Unknown Record (possible scope error?)

If I have a list of "albums," and I click on one, I navigate to another view (/#/album/:id) which is controlled by a controller called SingleAlbum. It fetches the data correctly, but I can't get it to render. I've looked over other 'Unknown Record' issues on SO and on the Spine Google Group, but no dice. Here's my code:
var SingleAlbum = Spine.Controller.sub({
apiObj: {
url: '/api/album',
processData: true,
data: {
id: ''
}
},
model: Album,
panel: $('.album_single'),
tmpl: $('#albumTpl'),
init: function() {
this.apiObj.url = this.model.url;
if(this.panel.children.length > 0) {
this.panel.html('');
}
},
render: function(id) {
console.log('render');
var template = singleAlbum.tmpl.html(),
data = Album.find(id), // <-- this doesn't want to work
html = Mustache.to_html(template, data);
singleAlbum.panel.html(html);
},
getData: function(id) {
//var me = this;
console.log('get data');
this.apiObj.data.id = id;
this.apiObj.url = this.model.url;
this.model.bind('refresh change', function(id) {
//me.render(id);
singleAlbum.render(id);
console.log('should be rendered');
});
this.model.fetch(this.apiObj);
console.log('record: ',this.model.find(id));
if(Object.keys(this.model.find(id)).length > 0) {
//this.render(id);
}
}
});
The problem happens when I call .render() on the event handler. I can manually see that Album.all() has records, and can do Album.find(id) anywhere else in the app, but when I do it on var data = Album.find(id) it fails. Is this a scope issue? Am I missing something obvious?
By the by, please excuse the verboseness of my code. I'm actually making a SingleItem controller, of which SingleArtist and SingleAlbum will be subclasses. I thought that might be an issue, so I ripped out the code to test it on it's own.
EDIT: Specifically, my route looks like this:
'/album/:id': function(params) {
console.log('navigated to /album/', params.id);
singleAlbum.getData(params.id);
}
Aha! I was passing id in my event handler, which was overwriting the other id variable. Here's what it should look like:
render: function(id) {
var template = this.tmpl.html(),
data = this.model.find(id),
html = Mustache.to_html(template, data);
this.panel.html(html);
},
getData: function(id) {
var me = this;
this.apiObj.data.id = id;
this.apiObj.url = this.model.url;
this.model.bind('refresh change', function() { // <-- don't need to pass anything
me.render(id);
});
this.model.fetch(this.apiObj);
}

Categories