Unknown provider: $xProvider <- $xService - angularjs

I'm having an issue with Karma and Jasmine while using AngularJS. What I'm trying to do is test a controller that will make some posts available to the view from a service. Here's my controller:
app.controller('PostController', function($scope, $postService) {
$scope.posts = $postService.getPosts();
});
And here is my test:
describe('PostController', function(){
var posts, $postService;
beforeEach(module('cms'));
beforeEach(function() {
posts = [
{
title: 'Article title',
tags: [
{ name: 'Tag #1', link: 'posts/tagged/tag-1' },
{ name: 'Tag #2', link: 'posts/tagged/tag-2' },
{ name: 'Tag #3', link: 'posts/tagged/tag-3' }
],
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur nisi nec neque molestie ultricies. ' +
'Mauris facilisis libero lorem. Praesent pulvinar dictum justo, at tincidunt magna convallis at. Integer' +
'laoreet justo vel faucibus placerat. Sed quis elit vel ante dictum dictum. Mauris ut ullamcorper tortor.' +
'Phasellus finibus ex justo, eget rutrum felis lobortis tincidunt. Curabitur hendrerit elit enim, a fermentum' +
'odio egestas mollis.',
author: { name: 'Dan', link: 'users/Dan-1' },
postDate: '0 seconds ago'
}
]
postService = {
getPosts: function() { return posts; }
};
})
it('should create "posts" model with posts from PostService', inject(function($controller) {
var scope = {},
ctrl = $controller('PostController', {$scope: scope, $postService: postService});
expect(scope.posts).toEqual(posts);
}));
});
The test works in this state, however I will be unable to run the controller at runtime because there is no explicit dependency;
Error: [$injector:unpr] Unknown provider: $postServiceProvider <- $postService
However, if I wrap the controller in something like this:
app.controller('PostController', ['$postService', inject(function($scope, $postService) {
$scope.posts = $postService.getPosts();
}
Then the controller will work at runtime, however in testing, $postService will always be undefined from inside of the controller.
Has anyone come across this issue, and if so, what am I missing here?

Try this:
you are missing $scope
app.controller('PostController', ['$scope', '$postService', function($scope, $postService) {
$scope.posts = $postService.getPosts();
}]);

Related

Referring to a json array file for swiftui

I am trying to write code so that each time the confirm answer button is clicked, the next question in the json array is called. There are five questions in this file and so far I can get the first and second question to appear. Is there anyway I could write a loop so that the next question is called each time the user enters confirm?
I am new to swiftui and so am unsure about how to proceed
import SwiftUI
struct SecondView: View {
var ResearchMCQ: Question
//Creating Variables for Revision Topics
#State private var setOptionOne = false
#State private var setOptionTwo = false
#State private var setOptionThree = false
let button = ["Confirm Answer"]
#State public var buttonConfirm: Int?
var body: some View {
ScrollView{
VStack(spacing: 1.0) {
Group {
Text(ResearchMCQ.question)
.padding(.trailing, 5)
//Ensures Only One Answer Can Be Selected
let OptionOne = Binding<Bool>(get: { self.setOptionOne }, set: { self.setOptionOne = $0; self.setOptionTwo = false; self.setOptionThree = false })
let OptionTwo = Binding<Bool>(get: { self.setOptionTwo }, set: { self.setOptionOne = false; self.setOptionTwo = $0; self.setOptionThree = false })
let OptionThree = Binding<Bool>(get: { self.setOptionThree }, set: { self.setOptionOne = false; self.setOptionTwo = false; self.setOptionThree = $0 })
VStack {
Toggle(ResearchMCQ.options[0], isOn: OptionOne)
.toggleStyle(.button)
.tint(Color(.gray))
.foregroundColor(Color("Black-White"))
Toggle(ResearchMCQ.options[1], isOn: OptionTwo)
.toggleStyle(.button)
.tint(Color(.gray))
.foregroundColor(Color("Black-White"))
Toggle(ResearchMCQ.options[2], isOn: OptionThree)
.toggleStyle(.button)
.tint(Color(.gray))
.foregroundColor(Color("Black-White"))
}
}
Spacer()
Spacer()
HStack(spacing: 15) {
ForEach(0..<button.count, id: \.self) {button in
Button(action: {
self.buttonConfirm = button
}) {
//Links Continue Button To Next Page
NavigationLink(destination: SecondView(ResearchMCQ: questions[1])) {
Text("Confirm Answer")
}
.padding(.vertical, 12.5)
.padding(.horizontal, 120)
.foregroundColor(.white)
.foregroundStyle(.background)
.background(2 == button ? Color.primary: Color.secondary)
.clipShape(Capsule())
}
}
}
}
.navigationTitle("")
}
}
}
struct SecondView_Previews: PreviewProvider {
static var previews: some View {
SecondView(ResearchMCQ: questions[0])
}
}
If all questions have a similar structure, there are a couple of ways to achieve that.
For example, in the parent view you can iterate through the array of questions and call each time SecondView with a different question. I recommend that approach.
Because you didn't provide the parent view code, I propose here below a way to iterate through the array directly in SecondView.
You can change the same view instead of navigating to another one. So, SecondView should hold all questions, not just one, and you change the index of the question you are showing.
The steps to follow are here below:
Have your view holding the whole array of questions and not only one question. By the way, in Swift variables are lower caps.
// Remember to pass the whole array of questions to this variable
let researchMCQ: [Question]
Have another variable to hold the current question.
#State private var questionIndex = 0
Also buttonConfirm should be an array in this case.
#State public var buttonConfirm = [Int?]()
Show the current question (see how the variable researchMCQ is used here).
Group {
Text(researchMCQ[questionIndex].question)
.padding(.trailing, 5)
The confirmation button doesn't need a NavigationLink, just change the index and the next question will be shown.
Button {
buttonConfirm.append(button)
// or this, if you initialize the var with the whole array:
// buttonConfirm[questionIndex] = button
// Make sure the index doesn't go beyond the array size
if researchMCQ.count > questionIndex + 1 {
questionIndex += 1
}
} label: {
Text("Confirm Answer")
}
You can use a #Statevar to remember the active index of your questions, and then just count up this index. By doing so there is no need for further views.
Usually you would count through the questions from a parent view and then have the child view display one single question (and answers).
struct Question: Identifiable {
let id = UUID()
var question: String
var options: [String] = ["One", "Two", "Three"]
}
struct ContentView: View {
// dummy data
let researchMCQ: [Question] = [
Question(question: "First Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
Question(question: "Second Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
Question(question: "Third Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
Question(question: "Fourth Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui")
]
// currently active question index
#State private var activeQuestionIndex = 0
//picked Option/Answer
#State private var pickedOption = 0
var body: some View {
VStack(spacing: 1.0) {
Group {
Text(researchMCQ[activeQuestionIndex].question)
.padding(.bottom)
Picker("Select Answer", selection: $pickedOption) {
Text(researchMCQ[activeQuestionIndex].options[0]).tag(0)
Text(researchMCQ[activeQuestionIndex].options[1]).tag(1)
Text(researchMCQ[activeQuestionIndex].options[2]).tag(2)
}
.pickerStyle(.segmented)
}
Spacer()
Button(action: {
if activeQuestionIndex < researchMCQ.count-1 {
self.activeQuestionIndex += 1
self.pickedOption = 0
}
}) {
Text("Confirm Answer")
}
.padding(.vertical, 12.5)
.padding(.horizontal, 120)
.foregroundColor(.white)
.foregroundStyle(.background)
.background(Color.primary)
.clipShape(Capsule())
}
.padding()
}
}

GraphQL only returning first node on Gatsby site

I'm using gatsby-source-mysql to pull some data from an internal tool where our users are able to create advertisements that can be displayed on our consumer site. I currently have four promos set up for testing, and this is the GraphQL query that I have to pull that data:
query PromoQuery($id: String) {
allMysqlPromos(filter: { id: { eq: $id } }) {
edges {
node {
ad_title
ad_filename
ad_body
URL_ext
phone
id
}
}
}
}
This is what's being returned. It's getting all four promos, which is exactly what I need.
{
"data": {
"allMysqlPromos": {
"edges": [
{
"node": {
"ad_title": "Buy One, Get One Free",
"ad_filename": "ad_002910.jpg",
"ad_body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam turpis quam venenatis porta sed. Aliquet eget lobortis quam ut dignissim eget quam lobortis. Elementum, at nullam tincidunt viverra pulvinar ac porta sed mauris. Sit leo imperdiet turpis morbi arcu, posuere odio sit.",
"URL_ext": "/promo-one",
"phone": "19167137108",
"id": "mysql__Promos__2910"
}
},
{
"node": {
"ad_title": "Buy Two, Get Two Free",
"ad_filename": "ad_002911.jpg",
"ad_body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam turpis quam venenatis porta sed. Aliquet eget lobortis quam ut dignissim eget quam lobortis. Elementum, at nullam tincidunt viverra pulvinar ac porta sed mauris. Sit leo imperdiet turpis morbi arcu, posuere odio sit.",
"URL_ext": "/promo-two",
"phone": "19165451660",
"id": "mysql__Promos__2911"
}
},
{
"node": {
"ad_title": "Buy Three, Get Three Free",
"ad_filename": "ad_002912.jpg",
"ad_body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam turpis quam venenatis porta sed. Aliquet eget lobortis quam ut dignissim eget quam lobortis. Elementum, at nullam tincidunt viverra pulvinar ac porta sed mauris. Sit leo imperdiet turpis morbi arcu, posuere odio sit.",
"URL_ext": "/promo-three",
"phone": "19168243634",
"id": "mysql__Promos__2912"
}
},
{
"node": {
"ad_title": "New Year's Special",
"ad_filename": "ad_002913.jpg",
"ad_body": "Our amazing New Year's Special will guarantee you 50% off of 150 doors. If your house is big enough to have 150 doors then you deserve several thousand dollars off.",
"URL_ext": "/promo-four",
"phone": "19163654393",
"id": "mysql__Promos__2913"
}
}
]
}
}
}
However, in the template for the individual promos, I'm getting the same content on all four, and it is only returning data from the first node i.e. all four different promos have 'Buy One, Get One Free' as the main heading etc. Here is my template for the promo pages, including the GraphQL query from above.
/* eslint-disable react/display-name */
import React, { useContext, useEffect } from 'react';
import ShareImage from 'assets/images/one-day-share-slogan.png';
import { SEO } from 'components/seo/SEO';
import { Row } from 'containers/row/Row';
import { CallRail } from 'contexts/callrail-context/CallRailContext';
import { graphql } from 'gatsby';
import { Content } from './promo/content/_Content';
import { CallToAction } from './promo/cta/_CallToAction';
import { Hero } from './promo/hero/_Hero';
export default (props: any) => {
const document = props.data.allMysqlPromos.edges[0];
if (!document) return null;
const { changeNumber } = useContext(CallRail);
const number = document.node.phone;
useEffect(() => {
changeNumber(number);
});
console.log(document.node.ad_title);
return (
<>
<SEO
title={document.node.ad_title}
desc={document.node.ad_body.substr(0, 150) + '...'}
banner={ShareImage}
/>
<Hero document={document.node} />
<Row>
<CallToAction />
<Content>{document.node.ad_body}</Content>
</Row>
</>
);
};
export const query = graphql`
query PromoQuery($ad_title: String) {
allMysqlPromos(filter: { id: { eq: $ad_title } }) {
edges {
node {
ad_title
ad_filename
ad_body
URL_ext
phone
id
}
}
}
}
`;
What am I doing wrong, and what do I need to change to get the correct data in for each promo page?
You should pass via context your filter value, in that case, the ad_title field. So, in your gatsby-node.js you should have something like:
createPage({
path: `/promo/${URL_ext}`, // or your value
component: individualPromoComponent, // or your component
context: {
ad_title: node.ad_title,
},
})
Now, you can use ad_title in your component using $ad_title in:
export const query = graphql`
query PromoQuery($ad_title: String) {
allMysqlPromos(filter: { id: { eq: $ad_title } }) {
edges {
node {
ad_title
ad_filename
ad_body
URL_ext
phone
id
}
}
}
}
`;

Angular 6 - Convert JSON to array

Hellog guys , i am trying to convert json data to object array for add these data to kendo grid but i am getting this error
Uncaught (in promise): TypeError: Cannot read property 'slice' of undefined
This error mean my data format isn't correct !.
This how data in json file are :
[
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
]
But i want them to be like this :
{
"data": [
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
],
}
Here an example of how i am accessing json file (orders.ts)
import { orders } from './orders';
import { employees } from '../employee/employees';
#Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.css']
})
export class OrderComponent implements OnInit {
public result;
public data = orders;
}
I tried many solutions like json.parse() and json.stringify() but didn't get what i need.
Note : I am using json file (orders.ts) that exist in my project.
var data = [
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
];
var newData = {
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
};
data.push(newData)
console.log(newData);
you can do it simply like this and make sure name is same as data
data=[
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
];
let d={data}
console.log(d)
or
let d={}
d.data=[
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
]
console.log(d)
you will get the desired output

When I console.log(portfoliosArray) it returns an array or four arrays?

Instead of returning an array of objects, pulling from a JSON file, it returns an array of 4 arrays containing 4 objects? Why? JSON file name is portfolios.json.
'use strict';
var portfolioArray = [];
function Portfolio (portfoliosDataObj) {
this.title = portfoliosDataObj.title;
this.body = portfoliosDataObj.body;
this.img = portfoliosDataObj.img;
}
Portfolio.prototype.toHtml = function() {
var renderPortfolios = Handlebars.compile($('#portfolio-template').text());
return renderPortfolios(this);
console.log(this);
};
$.getJSON('/data/portfolios.json', function(portfolios) {
portfolios.forEach(function(portfoliosDataObject) {
var portfolio = new Portfolio(portfoliosDataObject);
portfolioArray.push(portfolios);
console.log(portfolios);
});
});
function print () {
portfolioArray.forEach(function(data) {
$('#portfolioSection').append(data.toHtml());
});
}
Portfolio();
print();
JSON FILE - Adding for reference.
[{
"title": "CodeFellows/Code201",
"body": "content1",
"img": ""
},
{
"title": "CodeFellows/Code301",
"body": "lorem ipsum"
},
{
"title": "Upcoming Projects/Other interest",
"body": "lorem impsum",
"img": "/images/blog.jpg"
},
{
"title": "Illustrations",
"body": "lorem ipsum",
"img": "/images/portfolio.png"
}]
IGNORE need more content that isn't code to post....
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam porttitor leo at tellus facilisis, id suscipit ipsum suscipit. Aenean venenatis, quam semper efficitur hendrerit, odio diam condimentum odio, id sagittis lorem tellus vel mauris. Cras enim neque, malesuada sit amet lacinia et, ullamcorper non sapien. Integer id hendrerit nulla, vitae tristique tortor. Aenean in arcu eget massa pulvinar dictum. Aliquam dictum fermentum sapien id iaculis. Ut malesuada varius lacinia. Maecenas scelerisque facilisis mattis.
The file returns an array of 4 objects, and not arrays.
{
"title": "CodeFellows/Code201",
"body": "content1",
"img": ""
}
is a javascript object, not an array (notice the curly braces {}).
The outer one is an array. (notice the square brackets[]).
You can get to the objects by doing a console.log(portfolios[0]);
The issue is with this code. You are pushing portfolios in portfolioArray instead of portfolio. Also you were doing console.log for portfolios which is why it was showing 4 arrays. I have fixed the code. Let me know if it works for you.
$.getJSON('/data/portfolios.json', function(portfolios) {
portfolios.forEach(function(portfoliosDataObject) {
var portfolio = new Portfolio(portfoliosDataObject);
portfolioArray.push(portfolio);
console.log(portfolio);
});
});

Sort an array in javascript based on another array

I have an array of Mongoose ID's as follows:
var ids =[
mongoose.Types.ObjectId('58c2871414cd3d209abf4fc1'),
mongoose.Types.ObjectId('58c2871414cd3d209abf4fc0'),
mongoose.Types.ObjectId('58c2871414cd3d209abf5fc0')
];
When I call my Mongoose function to get the subdocuments that match these ids, the objects are returned to me in order of how they are found in the database. Can I reorder these based on the order of the above 'ids' array?
The data returned to me is as follows:
[ { _id: 58c2871414cd3d209abf5fc9,
companyname: 'Dell',
position:
{ _id: 58c2871414cd3d209abf5fc0,
title: 'Software Engineer',
location: 'Waterford',
start: 'May 2017',
term: 6,
description: ' Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis erat vitae dsit amet, consectetur adipiscing elit. Vivamus quis erat vitae dolor tempus euismod non in mi' },
{ _id: 58ca9fd6588205e9c8f01431,
companyname: 'Google',
position:
{ _id: 58c2871414cd3d209abf4fc0,
title: 'Software Engineer',
location: 'Waterford',
start: 'May 2017',
term: 6,
description: ' Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis erat vitae dsit amet, consectetur adipiscing elit. Vivamus quis erat vitae dolor tempus euismod non in mi' },
{ _id: 58ca9fd6588205e9c8f01431,
companyname: 'Google',
position:
{ _id: 58c2871414cd3d209abf4fc1,
title: 'Software Engineer',
location: 'Waterford',
start: 'June 2017',
term: 12,
description: ' Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis erat vitae dsit amet, consectetur adipiscing elit. Vivamus quis erat vitae dolor tempus euismod non in mi' },
]
Is there any way of re-ordering these based on the original array? Note there are two _ids returned in the array, its the id for the position sub-document that I need to order. Really stuck if anyone could help that would be great!
EDIT:
My Node.js function is as follows:
var ids =[mongoose.Types.ObjectId('58c2871414cd3d209abf4fc0'), mongoose.Types.ObjectId('58c2871414cd3d209abf4fc1'), mongoose.Types.ObjectId('58c2871414cd3d209abf5fc0')];
User.aggregate( { $unwind : "$position" },
{ $match: { "position._id": {
$in: ids }
}
}
, function(err, results){
// results.sort((a, b) => {
console.log(a+" "+b);
// return ids.indexOf(mongoose.Types.ObjectId(a.position._id))
// - ids.indexOf(mongoose.Types.ObjectId(b.position._id))
// })
res.send({results:results});
});
});
Logged in console:
[object Object] [object Object]
[object Object] [object Object]
You can use Array.prototype.sort() with a compare function, the compare function finds the index of each element in ids using Array.prototype.indexOf() and giving it element.postion.id.
Here is the code:
data.sort((a, b) => {
return ids.indexOf(a.position._id) - ids.indexOf(b.position._id)
})
I used _id as a string, You have to change it to mongoose.Types.ObjectId()
I think it's done like that
data.sort((a, b) => {
return ids.indexOf(mongoose.Types.ObjectId(a.position._id)) - ids.indexOf(mongoose.Types.ObjectId(b.position._id))
})

Resources