Ionic app - controller $http - javascript

I am building a app in ionic, i am trying to get external restful api data into the view via a controller, but there seems to be something wrong with my controller because nothing is being pulled in?
my code is:
angular.module('starter', ['ionic'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.controller('myCtrl', function($scope, $http) {
$http.get('http://jsonplaceholder.typicode.com/posts').then(function(results){
$scope.posts = results.data.posts;
}, function(err) {
console.error('ERR', err);
// err.status will contain the status code
})
});
<ion-content class="has-subheader" ng-controller="myCtrl">
<ion-list>
<ion-item ng-repeat='item in posts' class="item-thumbnail-left item-text-wrap">
<img src="http://placehold.it/100x100" alt="photo">
<h2>{{post.title}}</h2>
<h4>Place</h4>
<p style="font-size:12px; line-height:16px;">Quisque quis sem a velit placerat vehicula quis nec felis. Mauris posuere, nisl vitae condimentum luctus, tellus enim blandit orci, quis efficitur nibh libero eget dui. Aliquam fermentum velit quis sem molestie.</p>
</ion-item>
</ion-list>
</ion-content>
Any help would be appreciated.

Solution to this:
$http.get('http://jsonplaceholder.typicode.com/posts')
.success(function(results){
$scope.posts = results.posts;
console.log($scope.posts);
});
You were using data but there isn't data in the results. Look at the console, and you should see objects now.
Working codepen

you have made 2 mistakes in your code:
First: once you define 'item' in ng-repeat you should use it to bind your object key "title":
ng-repeat='item in posts'
'item' is now holding your JSON keys.
<h2>{{item.title}}</h2>
Second: reviewing jsonplaceholder JSON you are calling through this url, http://jsonplaceholder.typicode.com/posts, title key is under results.data
, so you should define posts like this:
$scope.posts = results.data
For more help: I've taken the code you provided and made it working on a plunk, check it on the following url:
http://embed.plnkr.co/Gp1U3y/preview
Please contact me for more help. Thanks

Related

TINYMCE Editor External Templates: Uncaught TypeError: Cannot read property 'indexOf' of undefined

I am using TINYMCE Editor Version 4.8.2 (2018-08-09) and trying to add few prebuilt templates in .html in the list. I installed the template plugin in the plugin directory and initiated it in init-tinymce.js as below.
tinymce.init({
/* replace textarea having class .tinymce with tinymce editor */
selector: "textarea",
/* plugin */
plugins: [
"template"
],
/* toolbar */
toolbar: "template",
/* templates */
templates: [
{
title : "Default Template 1",
src : "tinymce-templates/template1.html",
description : "Default Template"
},
{
title : "Default Template 2",
src : "tinymce-templates/template2.html",
description : "Default Template"
}
]
});
Now when I try to open and insert my added templates then I am able to see my both template in the dropdown list but when I cant see the preview. On inspecting, I found this error shared below.
Uncaught TypeError: Cannot read property 'indexOf' of undefined plugin.min.js:1
at S (plugin.min.js:1)
at i.onselect (plugin.min.js:1)
at Vg.c.fire (tinymce.min.js:2)
at i.fire (theme.min.js:1)
at w (plugin.min.js:1)
at plugin.min.js:1
at i.<anonymous> (plugin.min.js:1)
at Vg.c.fire (tinymce.min.js:2)
at i.fire (theme.min.js:1)
at HTMLDivElement.o (theme.min.js:1)
S # plugin.min.js:1
onselect # plugin.min.js:1
Vg.c.fire # tinymce.min.js:2
fire # theme.min.js:1
w # plugin.min.js:1
(anonymous) # plugin.min.js:1
(anonymous) # plugin.min.js:1
Vg.c.fire # tinymce.min.js:2
fire # theme.min.js:1
o # theme.min.js:1
C # tinymce.min.js:2
d
And my template is like something below...
<div class="mceTmpl">
<div class="row">
<div class="box">
<div class="col-lg-12">
<hr>
<h2 class="intro-text text-center">Build a website
<strong>worth visiting</strong>
</h2>
<hr>
<hr class="visible-xs">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc placerat diam quis nisl vestibulum dignissim. In hac habitasse platea dictumst. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
</div>
</div>
</div>
</div>
I believe where you have a src attribute the correct attribute is url. Per the documentation I see this:
This option lets you specify a predefined list of templates to be
inserted by the user into the editable area. It is structured as an
array with each item having a title, description and content/url.

How do I update blog post in Mongoose?

I am building a blog site using CRUD operations. I can create, read and delete but I am having hard time with updating a created post.
Basically I have it where I can click on the "edit" button on an individual entry in home.ejs and into the edit.ejs route where that input fields are populated with current title and content. But what I can not figure out is clicking "Publish" in edit.ejs to update its own post.ejs title and content. When it is done, I want to redirect it back to the main page. Down on the "app.post("/edit/:id")" route, am I supposed to use "PUT" request to update the post?
I am sorry if this is tough to follow. I am not very good at explaining things.
Here's the relevant code:
app.js
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const _ = require("lodash");
const aboutContent = "Hac habitasse platea dictumst vestibulum rhoncus est pellentesque. Dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Non diam phasellus vestibulum lorem sed. Platea dictumst quisque sagittis purus sit. Egestas sed sed risus pretium quam vulputate dignissim suspendisse. Mauris in aliquam sem fringilla. Semper risus in hendrerit gravida rutrum quisque non tellus orci. Amet massa vitae tortor condimentum lacinia quis vel eros. Enim ut tellus elementum sagittis vitae. Mauris ultrices eros in cursus turpis massa tincidunt dui.";
const contactContent = "Scelerisque eleifend donec pretium vulputate sapien. Rhoncus urna neque viverra justo nec ultrices. Arcu dui vivamus arcu felis bibendum. Consectetur adipiscing elit duis tristique. Risus viverra adipiscing at in tellus integer feugiat. Sapien nec sagittis aliquam malesuada bibendum arcu vitae. Consequat interdum varius sit amet mattis. Iaculis nunc sed augue lacus. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing elit. Pulvinar elementum integer enim neque. Ultrices gravida dictum fusce ut placerat orci nulla. Mauris in aliquam sem fringilla ut morbi tincidunt. Tortor posuere ac ut consequat semper viverra nam libero.";
let app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static("public"));
mongoose.connect("mongodb://localhost:27017/blogDB", {
useNewUrlParser: true
});
const postSchema = {
date: String,
title: String,
content: String
}
const Post = mongoose.model("Post", postSchema);
app.get("/", (req, res) => {
Post.find({}, (err, posts) => {
res.render("home", {
posts: posts
});
});
});
app.get("/about", (req, res) => {
res.render("about", {
aboutContent: aboutContent
});
});
app.get("/contact", (req, res) => {
res.render("contact", {
contactContent: contactContent
});
});
app.get("/compose", (req, res) => {
res.render("compose");
});
app.post("/compose", (req, res) => {
const postTitle = req.body.postTitle;
const postBody = req.body.postBody;
let date = new Date();
let postDate = date.toLocaleString('en-US');
const post = new Post({
date: postDate,
title: postTitle,
content: postBody
});
post.save(err => {
if (!err) {
res.redirect("/");
}
});
});
app.get("/edit/:id", (req, res) => {
const requestedId = req.params.id;
console.log(req.body);
Post.findOne({
_id: requestedId
}, (err, post) => {
if (!err) {
res.render("edit", {
title: post.title,
content: post.content
});
}
});
});
app.post("/edit/:id", (req, res) => {
const requestedId = req.params.id;
console.log(req.body);
Post.findOne({
_id: requestedId
}, (err, post) => {
if (!err) {
res.render("edit", {
title: post.title,
content: post.content
});
}
});
});
app.get("/posts/:id", (req, res) => {
const requestedId = req.params.id;
Post.findOne({
_id: requestedId
}, (err, post) => {
if (!err) {
res.render("post", {
title: post.title,
content: post.content
});
}
});
});
app.post("/delete", (req, res) => {
const deletePost = req.body.delete;
Post.findByIdAndDelete(deletePost, (err) => {
if (!err) {
res.redirect("/");
}
});
});
app.listen(3000, function () {
console.log("Server started on port 3000");
});
home.ejs
<%- include("partials/header") -%>
<h1>Home</h1>
<button type="button" class="new-entry btn btn-dark">New Entry</button>
<div class="entries-container">
<% posts.forEach(post => { %>
<div class="blog-entry">
<p class="post-date">Posted on
<%= post.date %>
</p>
<h2>
<%= post.title %>
</h2>
<div class="entry-footer">
<button type="button" class="btn btn-outline-primary">VIEW</button>
<form action="/edit" method="POST">
EDIT</button>
</form>
<form action="/delete" method="POST">
<button type="submit" name="delete" value="<%= post._id %>" class="btn btn-outline-danger">DELETE</button>
</form>
</div>
</div>
<% }) %>
</div>
<%- include("partials/footer") -%>
edit.ejs
<%- include("partials/header") -%>
<h1>Compose</h1>
<form action="/edit" method="PUT">
<div class="form-group">
<label for="postTitle">Title</label>
<input type="text" name="postTitle" class="form-control" id="postTitle" autocomplete="off" value="<%= title %>">
<label for="postBody">Post</label>
<textarea name="postBody" class="form-control" autocomplete="off" rows="8"><%= content %></textarea>
</div>
<button type="submit" name="button" class="btn btn-primary">Publish</button>
</form>
<%- include("partials/footer") -%>
post.ejs
<%- include("partials/header") -%>
<h2 class="post-title"><%= title %></h2>
<p class="post-content"><%= content %></p>
<%- include("partials/footer") -%>
If you want to simply update your existing blog post title and content with sending POST request then you can do it with findOneAndUpdate() as below:
app.post("/edit/:id", (req, res) => {
const requestedId = req.params.id;
console.log(req.body);
Post.findOneAndUpdate({
_id: requestedId // Query Part
},
{
$set: {
title: req.body.title, // Fields which we need to update
content: req.body.content
}
},
{
new: true // option part ( new: true will provide you updated data in response )
},(err, post) => {
if (!err) {
res.render("edit", {
title: post.title,
content: post.content
});
}
});
});

Changed nothing, suddenly recieving Ionic TypeError co.event is undefined

I don't have much information, because it's the weirdest problem I have ever had.
I'm writing an app in Ionic 2. Last night I went to bed with everything being fine. I get up this morning to continue work and even though the Welcome Page loads, when you scroll through to the Home Page I get an error that co.event is undefined.
Here's a screenshot of the spectacularly unhelpful error message (why can't I copy paste error messages from this error screen in Ionic? So stupid). Searching "co.event" in my codebase returns 0 results.
I had not changed a single line of code anywhere. I don't even understand how this is possible, let alone what to do to fix it.
I switched from the branch I was working on to Master branch to see if that was still fine. No, that has a completely different error despite zero changes being made to that either.
I can solve the error on master branch by going into src/app/app.component.ts and commenting out this.initializeApp(); which makes everything work but seems like a really bad idea because that sounds like a pretty crucial line to include.
constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
// this.initializeApp();
// used for an example of ngFor and navigation
this.pages = [
{ title: 'Welcome', component: WelcomePage },
{ title: 'Home', component: HomePage },
{ title: 'List', component: ListPage }
];
}
Any help much appreciated.
Edit updates:
Here's my initializeApp
initializeApp() {
this.platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
this.statusBar.styleDefault();
this.splashScreen.hide();
// Enable to debug issues.
// window["plugins"].OneSignal.setLogLevel({logLevel: 4, visualLevel: 4});
var notificationOpenedCallback = function(jsonData) {
console.log('notificationOpenedCallback: ' + JSON.stringify(jsonData));
};
// window["plugins"].OneSignal
// .startInit("yyyyyyyyy", "yyyyyyyyy")
// .handleNotificationOpened(notificationOpenedCallback)
// .endInit();
});
}
And here's the THIRD different error (despite having literally changed nothing????) that appears when running the dev branch on my Android phone instead of in ionic serve. Master branch works fine on Android phone.
Edit 2: Home page code
<ion-header>
<ion-navbar>
<button ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Home</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h1 class="header">Nuevo NiƱo</h1>
<hr />
<div ng-app ng-init="qty=1;cost=2">
<button ion-button (click)="setData()">SetData</button>
<button ion-button (click)="getData()">GetData</button>
<br />
<b>Name:</b> {{name}}
<hr />
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="HomePage.qty">
</div>
<div>
Costs: <input type="number" min="0" ng-model="cost">
</div>
<div>
<b>Total:</b> {{qty * cost | currency}}
</div>
</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis ipsum id libero auctor viverra eget vitae ipsum. Aenean ultrices diam odio, ac vulputate felis ultrices vel. Donec a mauris tristique, feugiat nunc nec, lacinia augue.
</p>
<ion-list>
<ion-item>
<ion-label>Expected Birth Date</ion-label>
<ion-datetime displayFormat="MMM DD YYYY" [(ngModel)]="event.month"></ion-datetime>
</ion-item>
<ion-item>
<p><b>Baby arrives {{ days_until_birth }}!</b></p>
</ion-item>
</ion-list>
<ion-list>
<ion-list-header>
Recent Notifications
</ion-list-header>
<ion-item>
<ion-avatar item-start>
<img src="assets/img/avatar-ben.png">
</ion-avatar>
<h2>Doctor Smith</h2>
<h3>24th January</h3>
<p>3 month check-up</p>
</ion-item>
<ion-item>
<ion-avatar item-start>
<img src="assets/img/avatar-han.png">
</ion-avatar>
<h2>Han</h2>
<h3>Look, kid...</h3>
<p>I've got enough on my plate as it is, and I...</p>
</ion-item>
<ion-item>
<ion-avatar item-start>
<img src="assets/img/avatar-leia.png">
</ion-avatar>
<h2>Leia</h2>
<h3>I can handle myself</h3>
<p>You will remove these restraints and leave...</p>
</ion-item>
</ion-list>
<!-- <button ion-button secondary menuToggle>Toggle Menu</button> -->
</ion-content>
and the .ts file
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import moment from 'moment';
import { Storage } from '#ionic/storage';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
name: string = 'John';
// public days_until_birth = moment('20171119', 'YYYYMMDD').fromNow();
// let data = moment()
// let data = moment().format('YYYYMMDD');
// let time = moment().format('HHmmss');
// console.log('today is: ', data + ' and time: ', time);
constructor(public navCtrl: NavController, public storage: Storage) {
}
ionViewDidLoad() {
this.storage.set('name', 'James');
}
setData(){
this.storage.set('name', 'Brett');
}
getData(){
this.storage.get('name').then((data) => {
console.log(data);
});
}
}
Okay so by your code we can get the following:
For the second error it's probably because you're trying to access plugins via your window object and plugins doesn't exist in it since there's no cordova available.
I highly sugest you using ionic-native since they made all work of wrapping plugins so we can have a better and simpler use of them.
if it's possible always call your plugins after checking if the platform if cordova, iOS or Android so it doesn't break your application when not testing on emulators (in production/test you can take out this checkings, but for production it's good to have), so try to use your code inside of a if(this.platform.is('cordova')){}.
The co.event error in your home is simply because you don't have an event variable declared in your HomePage, thus it can't recognize the event and event.month. So i sugest check all your home page bindings and .ts variables and functions.
Hope this helps.

Angularjs - UI Boostrap: Accordion Open and close all

i have written some code to open and close all tabs of an accordion respectively use a separate 'open' and 'close' button. How ever it requires me to dynamically add a key value pair(a Boolean value) to my json data.
What is the best practice in this situation? should i add the Boolean value as a static json element or is it OK to dynamically add values when their sole purpose is for visual structure and not relevant to actual object data.
HTML/Angular directives
<div id="app" ng-app="demoApp">
<div id="controller" ng-controller="demoAppCtrl">
<uib-accordion close-others="false">
<div class="btn-group form-group">
<button type="button" class="btn btn-warning" ng-click="toggle(true)">Open</button>
<button type="button" class="btn btn-warning" ng-click="toggle(false)">Close</button>
</div>
<uib-accordion-group is-open="hero.state" ng-click="setOpened(false)" ng-repeat="hero in heroes">
<uib-accordion-heading>
{{hero.name}}
</uib-accordion-heading>
{{hero.bio}}
</uib-accordion-group>
</uib-accordion>
</div>
</div>
Javascript/Angular
var app = angular.module('demoApp', ['ngAnimate','ui.bootstrap']);
app.controller('demoAppCtrl', function($scope) {
// This json object contain only one entry as an example
$scope.heroes = [
{'name': 'Captain America', 'team': 'Avengers', 'bio': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vitae metus placerat, condimentum nisl et, accumsan sapien. Quisque molestie magna nulla, id malesuada sem interdum a.'}
];
$scope.addDefaultState = function(val) {
for (var i=0;i<$scope.heroes.length;i++) {
$scope.heroes[i].state = val;
}
}
$scope.addDefaultState(false);
$scope.toggle = function(status) {
$scope.heroes.forEach(function(e) {
e.state = status;
});
}
});
codepen.io - Working example (with corrections)
In my opinion the static json should not contain Boolean state value. It is okay to dynamically add values for visual presentation.
In your code the function addDefaultState is not needed. The is-open="hero.state" will take care of default state cause initially it will not find state and will consider it as false. So you change your code like below it should work too:
var app = angular.module('demoApp', ['ngAnimate','ui.bootstrap']);
app.controller('demoAppCtrl', function($scope) {
// This json object contain only one entry as an example
$scope.heroes = [
{'name': 'Captain America', 'team': 'Avengers', 'bio': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vitae metus placerat, condimentum nisl et, accumsan sapien.'}
];
$scope.toggle = function(status) {
$scope.heroes.forEach(function(e) {
e.state = status;
});
}
});

AngularJS - Using multiple forms

I'm pretty new to AngularJS, and in my inquisitive nature have attempted (and succeeded in most respects) in writing a news page, that allows users to comment on each article.
What I'm totally unhappy with though is my use of classic Javascript to get the story from the forms dynamically; you can see that I'm creating input fields that I am using a GetElementById on. Is there anyway to tidy this up with the two way data binding? I originally did this, but my lack of knowledge meant that the model was bound to BOTH forms; what would the the 'Angular' way around this? Primarily I can see that the addComment function is just Javascript - I know I can do this more succinctly in JQuery, but don't want to. I've got it working with a single 'comment' just fine, but can't see how I would approach multiple.
The second part is my form validation doesn't work. My guess is that my stab into it isn't great.
var app = angular.module("ngStoryTime", []);
var _stories = [
{
Id: 1,
Title: 'Man Falls Off The World!',
Body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
Date: '7 March 2015',
Images: [],
Comments: [{ Body:'LOL!', Name:'Michael', Date:'1 April 2015' }, { Body:'Tis a shame that.', Name:'William', Date:'1 April 2015' }]
},
{
Id: 2,
Title: 'Woman Eats Badger!',
Body: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum',
Date: '8 March 2015',
Images: [],
Comments: []
}
];
app.controller('StoryController', function($scope){
$scope.pageTitle = 'Welcome to the StoryTime website!';
// Initialise the story, and blank Comment property here
this.Stories = _stories;
this.addComment = function(story){
// Is there a better way to do this??
var commentValue = document.getElementById('txtComment_' + story.Id);
var nameValue = document.getElementById('txtName_' + story.Id);
// Create the object that holds the new comment value
var myNewComment = {
Body: commentValue.value,
Name: nameValue.value,
Date: '1 May 2015'
};
// Add the comment to the array
story.Comments.push(myNewComment);
commentValue.value = '';
nameValue.value = '';
};
});
<body ng-controller='StoryController as storyCtrl'>
<h1>{{pageTitle}}</h1>
<!-- Alias the controller for use in this section -->
<div ng-repeat="story in storyCtrl.Stories">
<!-- For each Story, detail and show it -->
<h2>{{story.Title}} </h2>
<h3>{{story.Date | date:'medium' }}</h3>
<p>{{story.Body}}
<div ng-repeat="comment in story.Comments">
<h4>{{comment.Name}} - {{comment.Date | date:'medium'}} </h4>
<em>"{{comment.Body}}"</em>
</div>
<!-- Show and hide an introduction depending on if a story has a comment, or not -->
<h4 ng-show="story.Comments.length > 0">Have a Comment? There are {{story.Comments.length}} comments made so far!</h4>
<h4 ng-show="story.Comments.length == 0">Have a Comment? Be the first to comment on this excellent piece of journalism</h4>
<!-- Start of the new form that holds the story's comments, we put the story's Id on all the HtmL so we can get this later, but i'm not sure if this is actually a good idea, yet. -->
<form name="frmStory_{{story.Id}}" ng-submit="storyCtrl.addComment(story)">
Name: <br />
<input id="txtName_{{story.Id}}" required /><br />
Comment:<br/>
<textarea id="txtComment_{{story.Id}}" required></textarea>
<button ng-disabled="frmStory_{{story.Id}}.$invalid">Add My Comment</button>
</form>
<hr/>
</div>
</body>
ng-model is a key here. Every time ng-repeat iterate through given collection it will create different scope for each piece of the repeated html code respectively to given object. Using ng-model allows you to manage the data in given scope.
<form name="frmStory_{{story.Id}}" ng-submit="storyCtrl.addComment(story)">
Name: <br />
<input ng-model="story.newComment.Name" required /><br />
Comment:<br/>
<textarea ng-model="story.newComment.Body" required></textarea>
<button ng-disabled="frmStory_{{story.Id}}.$invalid">Add My Comment</button>
</form>
Secondly in your code :
this.addComment = function(story)
you are referencing to the instance of the controller, better way to do this is bind everything that has connection with view with $scope
$scope.addComment = function(story)
More about ng-model: https://docs.angularjs.org/api/ng/directive/ngModel
Understaning angular model and scope system is a huge milestone to understand the Angular way to build apps. I encourage you to start with that.
Write functions in your controller this way:
$scope.yourFunctionName = function () {
}
More info here: https://docs.angularjs.org/guide/controller
As far as the form validation failing, can you paste some error messages you are getting?

Categories

Resources