我正在使用AngularJS开发Chrome扩展程序。
我使用以下内容脚本代码将控制器附加到网页所需的DOM元素
setController() {
if(this.setContollerCondition) {
this.controllerElement.attr('ng-controller', 'Controller as cntrl');
}
}
这种方法并不总是有效,因为控制器构造函数没有被调用,而且' ng-scope'不适用于该元素。
我想问一下,动态连接控制器的正确方法是什么。
如果这种方法是正确的,我可能会出错?
以下是页面加载时Chrome扩展程序中发生的活动的流程。
几乎所有函数都是异步调用。
目前发生的行为如下
该项目使用Webpack和ES6。
以下文件与实际代码类似,可帮助您更好地理解问题。
的manifest.json
{
"manifest_version": 2,
"name": "MyExtension",
"short_name": "MyExtension",
"omnibox": {
"keyword": "MyExtension"
},
"description": "Description",
"version": "2.0.7",
"version_name": "2.0.7",
"browser_action": {
"default_icon": {
"128": "assets/images/icon-v2-128px.png",
"16": "assets/images/icon-v2-16px.png",
"48": "assets/images/icon-v2-48px.png"
},
"default_title": "MyExtension",
"default_popup": "index.html"
},
"content_scripts": [ {
"js": [ "assets/lib/angular.min.js", "assets/lib/jquery-2.2.3.min.js", "assets/lib/bootstrap.min.js", "dist/contentScript.bundle.js" ],
"css": ["assets/css/font-awesome.min.css", "assets/css/bootstrapInject.css", "assets/css/injectingStyle.css"],
"matches": ["*://*.linkedin.com/*", "*://web.whatsapp.com/*", "*://mail.google.com/*"],
"run_at": "document_end"
} ],
"background": {
"page": "background.html"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"contextMenus",
"notifications",
"unlimitedStorage",
"storage"
],
"icons": {
"128": "assets/images/icon-v2-128px.png",
"16": "assets/images/icon-v2-16px.png",
"48": "assets/images/icon-v2-48px.png",
"16": "assets/images/icon-v2-16px.png"
},
"web_accessible_resources": [
"all required files here"
],
"update_url": "https://clients2.google.com/service/update2/crx",
"content_security_policy": "script-src 'self' 'unsafe-eval' https://ssl.google-analytics.com https://connect.facebook.net https://platform.twitter.com https://staticxx.facebook.com; object-src 'self'"
}
以下是附加控制器的 init.js
export default class AddContactModule {
constructor() {
// Check for the webpage we are currently in (linkedin, facebook, twitter, naukri, whatsapp, mail.google)
this.currentHost = window.location.host.split('.');
this.app = 'extension-extension';
// Variable to intialize parent of button we will add
this.globalButtonVar = '';
this.copyglobalButtonVar = '';
this.globalFormTemplate = '';
this.globalForm = '';
this.isLoggedin = false;
// Get ng-app param and check if its already present if it is then no need to intialize angular module again
this.ifAppDirective = document.querySelector('[ng-app]');
console.log("hello1");
this.init();
}
init() {
this.eventHandling();
this.addContactModel();
this.checkHost();
}
// Function to set the flag to check if user is logged in or not
eventHandling() {
if (!this.ifAppDirective && !$('.ng-scope').length) {
// If ng-app is not initialized initialize ng-app
$('body').attr('ng-app', this.app);
this.miscellaneousEvent();
}
}
// Function to call when user syncing images
// Function to handle other events
miscellaneousEvent() {
$(document).on('click', '.dropdown-menu .input-group-btn, .dropdown-menu .checkbox, .dropdown-menu a', function (e) {
e.stopPropagation();
});
// Cancel the fetch list dialoge box
$('body').on('click', '#fetchContainer-step2 > .innerContainer .close-fetch, .close-intro, .close-dialog', function() {
let thisEle = $(this).attr('id');
let scope = angular.element($('.pane.pane-three')).scope();
scope.$apply(function() {
scope.contact.cancelFetch(false, thisEle);
});
});
// Close the notification of start sync message
$('body').on('click', '#extension-close-notice', function(event) {
let scope = angular.element($('#extension-close-notice')).scope();
scope.$apply(function() {
scope.closeNotification();
});
});
// If clicked on linkedin save button open call the trigger function to open contact details
$('body').off('click', '#linkedin-save').on('click', '#linkedin-save', function() {
let scope = angular.element($('#profile-wrapper')).scope();
scope.$apply(function() {
scope.contact.linkedinFetch();
});
});
// trigger save function for gmail
$('body').off('click', '#gmail-save').on('click', '#gmail-save', function() {
let scope = angular.element($('.nH.g.id')).scope();
scope.$apply(function() {
scope.gmailFetch();
});
});
}
// Function to handle addcontactmodel open/close events
addContactModel() {
$('body').on('show.bs.modal', '#addContactModal', function () {
$(this).after('<div class="modal-backdrop fade in"></div>');
}).on('hide.bs.modal', '#addContactModal', function () {
$('.modal-backdrop').remove();
});
$('body').off('shown.bs.modal', '#addContactModal').on('shown.bs.modal', '#addContactModal', (event) => {
let openedBy = $(event.relatedTarget);
this.loginStatus();
// Check for the target popup is opened by whatzup from group
if(openedBy.hasClass('whatsappGroupBtn') || openedBy.hasClass('whatsappGroupChat')) {
let contactObj = {
ContactMobile: openedBy.data('contactnumber'),
given: openedBy.data('name'),
profilePic: openedBy.data('profilepic'),
};
// Reduce size of modal for group detail page
if(openedBy.hasClass('whatsappGroupBtn')) {
contactObj.addFrom = 'wa_group';
} else {
contactObj.addFrom = 'wa_chat';
}
// Assigne all found details to form, for this call controller function
let scope = angular.element($('#addContactForm')).scope();
// Set form to its default state
scope.$apply(() => {
scope.contact.updateForm(contactObj);
});
}
}).off('hidden.bs.modal', '#addContactModal').on('hidden.bs.modal', '#addContactModal', () => {
$('.arrowPointing').hide();
// Assigne all found details to form, for this call controller function
let scope = angular.element($('#addContactForm')).scope();
// Set form to its default state
scope.$apply(() => {
scope.contact.addNewContact = false;
// Helps to decide if the contact should be added to existing or new
scope.contact.addtoExisting = false;
scope.contact.noContact = false;
// Contains searched contact list
scope.contact.contactList = [];
// Search field model, this will have the searching text
scope.contact.searchKey = '';
scope.contact.searchCompleted = false;
scope.contact.globalTimeout = 0;
//lets you add another unknown contact when one unknown already has been added
scope.contact.contactAdded = false;
scope.contact.contactSaved = false;
});
});
}
// Hide/show login arrow depends on the login status
// Depends on host call linkedin init or facebookinit
checkHost() {
switch(this.currentHost[1]) {
case 'linkedin': {
this.initLinkedin();
break;
}
case 'google': {
this.initGmail();
break;
}
case 'whatsapp': {
this.initWhatsapp();
} default: {}
}
}
// Function to add template & button to linkedin
initLinkedin() {
// Variable to check if the button we are adding is in extra info section or not
let ifTablist = 1;
let linkedinForm = '';
// Button template if adding to extra info section
let buttonTemplate = '<span class="inline-block extension-save-button"><button type="button" id="linkedin-save" class="secondary top-card-action link-without-visited-state"><img src="https://d73xd4ooutekr.cloudfront.net/v4/img/logo-42.png"> Save Contact</a></span>';
let buttonContainerLength = 0;
// Get the parent
$('body').on('DOMNodeInserted', (event) => {
if(event.target.id == 'profile-wrapper' && !buttonContainerLength) {
this.globalButtonVar = this.copyglobalButtonVar = $('body').find('#profile-wrapper');
buttonContainerLength = this.globalButtonVar.find('.pv-top-card-section__actions').length;
// Check if the selected parent is not present
if(buttonContainerLength) {
this.globalButtonVar.find('.pv-top-card-section__actions').append(buttonTemplate);
this.setController();
}
}
});
}
// Function to set ng-controller
setController() {
if(this.globalButtonVar.length) {
this.globalButtonVar.attr('ng-controller', 'ContactModalController as contact');
}
}
}
以下是 controller.js 文件
"use strict";
import AddContactModule from './init'
export default class ContactModalController {
constructor($scope, $compile) {
// Intializing dependencies to the scope variable
this.$scope = $scope;
this.$compile = $compile;
/* Assign required objects which need to make everything works */
}
// Function to fetch linkedin details
linkedinFetch() {
// Show more button, this will show all contact details of current user
let saveBtn = $('.contact-see-more-less')
if(saveBtn.attr('data-control-name') == 'contact_see_more') {
saveBtn.click();
}
this.resetModal();
this.grabContactDetails.getLinkedinDetails(this.$scope, (response) => {
this.contactObj = response;
// default selected List
this.contactObj.selectedList = [];
$('#addContactModal').modal('show');
});
}
}
答案 0 :(得分:0)
我遇到了类似的问题,控制器没有初始化。
我在HTML标记上设置应用,并在正文标记上设置控制器。
根据我的问题,因为DOM元素的动态加载